问题引入
百度百科:八皇后问题
简述:
在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
这是一个典型的DFS回溯算法应用题,通过解这个题可以明确DFS算法的思路和步骤。
思路
由问题知道每行每列每条对角线都只能有一个皇后,所以需要用数组来记录每种条件的使用情况。其中每行的使用情况可以作为参数放在方法中,并为结束条件提供便利。
DFS算法基本步骤
要注意递归结束条件和回溯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| static void dfs(){ if (...) {return;} fori(){ if(递归条件){ ... dfs(); ... } } }
|
注意
值得注意的是对角线的维护数组的创建思路
主对角线:row - col规律如图

次对角线:row + col规律

主次对角线各14条,主对角线main_diagonal[row - col + 7] 即是对应某条主对角线的使用状态,同理次对角线为sec_diagonal[row + col]
打印所有92种排列的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public class 八皇后问题 { static final int EI = 8, FT = 15; static int[][] map = new int[EI][EI]; static boolean[] col = new boolean[EI]; static boolean[] main_diagonal = new boolean[FT]; static boolean[] sec_diagonal = new boolean[FT]; static int result = 0;
static void dfs(int n){ if (n >= EI){ soutMap(); return; } for (int i = 0; i < EI; i++) { if (check(n , i)){ map[n][i] = 1; act(n, i, true); dfs(n + 1); act(n, i, false); map[n][i] = 0; } } } static boolean check(int n, int i){ return !col[i] && !main_diagonal[n - i + EI - 1] && !sec_diagonal[n + i]; } static void act(int n, int i, boolean rel){ col[i] = rel; main_diagonal[n - i + EI - 1] = rel; sec_diagonal[n + i] = rel; } static void soutMap(){ result++; for (int[] i : map){ for (int j : i){ if(j == 1) System.out.print("*" + " "); else System.out.print("0" + " "); } System.out.println(); } System.out.println("++++++++++++++++++++"); }
public static void main(String[] args) { dfs(0); System.out.println("总共有" + result + "种排列方式!"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ...... ++++++++++++++++++++ 0 0 0 0 0 0 0 * 0 0 * 0 0 0 0 0 * 0 0 0 0 0 0 0 0 0 0 0 0 * 0 0 0 * 0 0 0 0 0 0 0 0 0 0 * 0 0 0 0 0 0 0 0 0 * 0 0 0 0 * 0 0 0 0 ++++++++++++++++++++ 0 0 0 0 0 0 0 * 0 0 0 * 0 0 0 0 * 0 0 0 0 0 0 0 0 0 * 0 0 0 0 0 0 0 0 0 0 * 0 0 0 * 0 0 0 0 0 0 0 0 0 0 0 0 * 0 0 0 0 0 * 0 0 0 ++++++++++++++++++++ 总共有92种排列方式!
|
总结
对于其他由此问题引出的皇后问题都可以参考此问题代码求解,只需更改特定方法或者参数即可。