Steam新調查結果顯示日區使用者猛增 愛玩PC遊戲了
阿新 • • 發佈:2022-04-19
n皇后問題:
* 給定一個n*n的棋盤,向該棋盤中放入n個皇后,使得n個皇后之間不在同行同列或同斜線,問有多少種方法
*
* 解題思路:
* 採用深度優先搜尋的思想:
* 1.整體上通過按行的思想,從第0行到第n-1行逐層深入進行遞迴。
* 2.每次遞迴時要記錄之前所有已經放好的皇后的位置,用於接下來判斷該行哪些位置能放皇后
1.未優化常數的方法
程式碼及解析:
1 public static int num1(int n) { 2 if (n < 1) { 3 return 0; 4 } 5 int[] record = new int[n];//開闢用於記錄0--n-1行皇后所在列位置的陣列空間 6 return process1(0,record,n); 7 } 8 9 /* 10 * i表示目前深度優先搜尋所尋找到的層數 11 * []record記錄了0——i-1層的皇后所在的列數位置 12 * n表示一共要探索的總層數 13 * 返回值:返回可以進行的擺放方式 14 */ 15 public static int process1(int i,int[] record,int n) {16 if (i == n) {//說明0——n-1層的皇后位置都被正常放好,可以返回一種有效的擺放方式 17 return 1; 18 } 19 int ans = 0; 20 for (int k = 0; k < n; k++) { 21 if (isValid(record,i,k)) {//如果在當前i-1層擺放的情況下,第i層第k列允許放一個皇后 22 record[i] = k; 23 ans += process1(i+1,record,n);24 } 25 } 26 return ans; 27 } 28 29 //判斷當前位置能否放入皇后 30 public static boolean isValid(int[] record,int i,int k) { 31 for (int j = 0; j < i; j++) { 32 if (record[j] == k || Math.abs(i - j) == Math.abs(record[j] - k)) { 33 return false; 34 } 35 } 36 return true; 37 }
2.優化方法:
優化思路:
* 使用數值中的每一位的0/1來表示皇后位置,第i位為1/0表示第i列有/無皇后
* 所以如果該列有了一個皇后,後續的皇后都不能在這一列。
* 而不能同斜線問題,則用位運算的左移和右移來進行實現
程式碼及解析:
1 //因為int最大值為2^32 - 1,所以我們討論不超過32皇后的問題 2 public static int num2(int n) { 3 if (n < 1 || n > 32) { 4 return 0; 5 } 6 int limit = 1 << n;//n個皇后只要用n位即可,但int數一共有32位,所以加一個限制條件,讓它只用n位 7 return process2(limit,0,0,0); 8 } 9 10 /* 11 * col用來處理皇后放置問題的列限制,1表示不能放皇后,0則可以 12 * left用來處理皇后放置問題的左斜線限制,1表示不能放皇后,0則可以 13 * right用來處理皇后放置問題的右斜線限制,1表示不能放皇后,0則可以 14 */ 15 public static int process2(int limit,int col,int left,int right) { 16 if (col == limit) {//所有列都不能放則說明n個皇后已放滿,形成了一個有效的放置情況 17 return 1; 18 } 19 int pos = limit & (~(col | left | right));//得到能放皇后的位置(即所有為1的位置) 20 int ans = 0; 21 while (pos != 0) { 22 int rightOne = pos & (~pos + 1);//獲取最右位,從該位(列)開始進行深度搜索 23 pos = pos - rightOne;//因為該列有了皇后,所以對pos進行更新 24 ans += process2(limit,col | rightOne,left | rightOne << 1,right | rightOne >> 1); 25 } 26 return ans; 27 }