八皇后算法解析(java代码演示)

来源:互联网 发布:深入浅出node.js 微盘 编辑:程序博客网 时间:2024/06/06 09:50

问题描述:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

图解:

1.首先我们需要一个8*8的空白棋盘;

2.在第0列的皇后我们可以随便摆放,因为是第一个皇后,不存在和其他皇后冲突的问题,所以我们从第0个位置开始摆放她;

3.第1列的皇后不能和第0列的皇后同行或在对角线,所以不能放在0和1行;

4.第2列的皇后不能和第0列和第一列的皇后同行或在对角线,所以不能放在0、 1、 2、 3行;

5.第3列的皇后不能和第0、 1、 2列的皇后同行或在对角线,所以不能放在0行,但是1行可以,我们就可以先这么放着,计算下一列;

通过以上这些解释,我们可以总结出来,当前列的行号m1与之前存放皇后的行号m0相等时,他们就在同一行了,即m1-m0=0,而如果行号差的绝对值与列号差相等时则在对角线,即Math.abs(m1-m0) == n1-n0.

6.第4列同样适用上面的法则,所以0、 1、 2行不能放;

7.第5列的时候你会发现0-7行都不能放皇后,这时候我们就需要回溯了,即返回第4列,重置第四列的皇后位置,然后再来计算第五列的,以后碰到8行都不能放皇后的时候都是这样处理,循环往复直至我们第一列的皇后放到第7行的所有结果都计算完结束。


思路整理:

1.首先定义一个一维整数数组用于存放每一列皇后所在的行号a[0]=0表示第0列的皇后放在了第0行;

2.循环8次,将第0列的皇后从0行一直循环放到7行,递归摆放其他列;

3.如果8列都摆放上了皇后,摆放方法计数器加一,打印当前摆放方法;

4.在8次循环中,从第0行开始判断是否满足当前行号m-a[i]==0即与之前的皇后在同一行,m-a[i]==n-i(n表示当前列号,i表示0至n-1的列号)即与之前的皇后在对角线,满足一项则该行不能放皇后,找到可以放皇后的位置后递归下一列,如果8行都不能放,则回溯到上一列把皇后位置向下放到满足条件的位置。


完整代码+注释:

package com.map.queen;public class Queen {//皇后的个数public final static int MAXQUEEN = 8;//皇后摆放方法的个数public static int num = 0;//每一列的皇后在该列中的行号public static int[] cols = new int[MAXQUEEN];/*** *  * @param n 当前列号 */public static void getCount(int n) {//如果8列都放上了皇后,则实现了一种摆放方法if(n==MAXQUEEN) {num++;System.out.println("第"+num+"种摆放方式:");printQueen();}//m代表的是行号for(int m=0; m < MAXQUEEN; m++) {//如果是第一列,则皇后摆放无限制,可以从0行到最后一行随便放if(n==0) {cols[n] = m;getCount(n+1);} else {int i = 0;//遍历之前所有摆放皇后的位置for(; i<n; i++) {//如果当前行号与前面摆放皇后的行号差值为0则在同一行不能摆放,//差值与列的差值相等则在对角线上不能摆放int d = Math.abs(m - cols[i]);if(d==0 || d==n-i) {break;}}//如果i与n相等代表当前的m行可以放皇后,不与前面的皇后位置冲突if(i==n) {cols[n] = m;getCount(n+1);}}}}/**打印皇后位置,0表示皇后*/private static void printQueen() {for(int i=0; i<MAXQUEEN; i++) {for(int j=0; j<MAXQUEEN; j++) {if(cols[j] == i) {System.out.print("0 ");} else {System.out.print("+ ");}}System.out.println("");}}public static void main(String[] args) {getCount(0);}}