1. 程式人生 > 其它 >遞迴解決八皇后問題

遞迴解決八皇后問題

遞迴解決八皇后問題

√八皇后問題說明

  • 八皇后問題,是一個古老而著名的問題,是回溯演算法的典型案例。

  • 該問題是國際西洋祺棋手馬克斯貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊

  • 即:任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。

√八皇后思路分析

1)第一個皇后先放第一行第一列 arr[8] = {0,0}

2)第二個皇后放在第二行第一列、然後判斷是否OK, 如果不OK,繼續放在第二列、第三列、依次把所有列都放完,找到一個合適

3)繼續第三個皇后,還是第一列、第二列.直到第8個皇后也能放 在一個不衝突的位置,算是找到了一個正確解

4)當得到一個正確解時,在棧回退到上一個棧時,就會開始回溯,即 將第一個皇后,放到第一列的所有正確解,全部得到.

5)然後回頭繼續第一個皇后放第二列,後面繼續迴圈執行1,2,3,4的 步驟

說明:理論上應該建立一個二維陣列來表示棋盤,但是實際上可以通 過演算法,用一個一維陣列即可解決問題

例如 : arr[8]={0,4,7,5,2,6,1,3} ,我們可以使用這樣的一維陣列來解決問題, 例如該陣列 就是將皇后擺放到 ,第一行的第一列 ,第二行的第五列 .........

 

程式碼示例(通過視訊參考,對著敲出來的)

public class Eight_questions {
  public static void main(String[] args) {

      checkerboard c1 = new checkerboard();
      c1.check(8,0);

  }
}

class checkerboard {
  int [] arr= new int[8];
  int count = 0;
  public void check(int n, int index) {
      if (n == index){
          for (int i = 0;i < n ;i++){
              System.out.print(arr[i]+" ");
          }
          count+=1;

          System.out.println();
          System.out.println("第"+count+"種擺放");

      }else {
          for (int i = 0;i < n ;i++){
              //此時的n代表列
              arr[index] = i;
              //第index行第i列
              if (judge(index)){
                  check(n,index + 1);
              }
          }
      }


  }

  public boolean judge(int index){
      for (int i=0;i<index;i++){
          if (arr[i]==arr[index]||Math.abs(index - i)==Math.abs(arr[index]-arr[i])){
              return false;
          }
      }
      return true;
      //如果不起衝突就返回true
  }

}

 

實際分析一下程式碼

class checkerboard

建立一個類 ,用於實現八皇后的棋盤填充

 int [] arr= new int[8];
//在類中建立一個全域性變數陣列,因為下面有兩個方法需要使用到
public void check(int n, int index) {
//建立方法check,傳參的引數 n為皇后棋子的個數,index表示從第幾行開始
      if (n == index){
      //如果棋子個數和和行數一致表示皇后已經全部下完
          for (int i = 0;i < n ;i++){
          //迴圈行數對陣列進行遍歷,然後將陣列的內容打印出來
              System.out.print(arr[i]+" ");
          }
          count+=1;
          System.out.println();
          System.out.println("第"+count+"種擺放");
      }
//如果陣列沒有完成填充(也就是八皇后的棋子沒有下完)
else {
      for (int i = 0;i < n ;i++)
      //迴圈
      {
          //此時的n代表列
          arr[index] = i;
          //迴圈填充陣列的內容
          //第index行第i列
          if (judge(index)){
          //接收judge方法來判斷這個位置是否符合規範,若符合規範就執行下面的遞迴
          check(n,index + 1);
          //遞迴呼叫方法,每次新增都會增加一次行數
        }
      }
  }
public boolean judge(int index){
//這個方法主要用於判斷皇后放置是否合法,接收引數index表示每行進行判斷
      for (int i=0;i<index;i++){
      //迴圈
          if (arr[i]==arr[index]||Math.abs(index - i)==Math.abs(arr[index]-arr[i])){
          //判斷陣列的上下兩行放置的列是否一致(如若一致表示皇后在同一列觸犯了規則)
          //判斷陣列的上下兩行,通過兩個位置橫縱座標互減如果數值一致就說明在一條斜線之上
          //同時由於不可能同行因此不判斷同行的情況
              return false;
              //如果不符合判斷就返回false
          }
      }
      return true;
      //如果符合規範就返回true
  }