N皇后问题是一个经典的问题,是回溯算法的典型案例。它是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的八皇后问题延伸而来的,具体要求如下:在N*N的方格棋盘放置N个皇后,使她们彼此不相互攻击,即任意2个皇后不允许在同一行、同一列、同一45°的斜线上,问有多少种摆法。
Java:
1 import java.util.Scanner; 2 3 /** 4 * n皇后问题解决 5 * 6 */ 7 public class N_Queens { 8 /**下标i表示第几行,x[i]表示第i行皇后的位置,注意此处0行不用*/ 9 public int[] x; 10 /**皇后的数目*/ 11 public int queenNum; 12 /**解的数目*/ 13 public int methodNum; 14 15 N_Queens(int queenNum) 16 { 17 this.queenNum = queenNum; 18 this.x = new int[queenNum+1];//注意,这里我们从第1行开始算起,第0行不用 19 backtrack(1);//从第一个皇后开始递归 20 } 21 22 /** 23 * 一行一行的确定该行的皇后位置 24 * @param t 25 */ 26 public void backtrack(int t) 27 { 28 if( t > queenNum) //如果当前行大于皇后数目,表示找到解了 29 { 30 methodNum++;//sum为所有的可行的解 31 //依次打印本次解皇后的位置 32 for(int m = 1; m <= queenNum; m++) 33 { 34 //System.out.println(x[m]);//这一行用输出当递归到叶节点的时候,一个可行解 35 //这里只是为了好看才写成下面的 36 for(int k =1; k <= queenNum;k++) 37 { 38 if(k == x[m]) 39 { 40 System.out.print(x[m]+" "); 41 } 42 else 43 { 44 System.out.print("* ");//用*表示没有被用到的位置 45 } 46 } 47 System.out.println(); 48 } 49 System.out.println(); 50 } 51 else 52 { 53 for(int i = 1;i <= queenNum;i++) 54 { 55 x[t] = i;//第t行上皇后的位置只能是1-queenNum 56 if(place(t)) //此处的place函数用来进行我们上面所说的条件的判断,如果成立,进入下一级递归,即放置下一个皇后 57 backtrack(t+1); 58 } 59 } 60 } 61 62 /** 63 * 判断第k行皇后可以放置的位置 64 * @param k k表示第k行,X[K]k表示第k行上皇后的位置 65 * @return boolean false表示此处不能放置皇后 66 */ 67 public boolean place(int k) 68 { 69 for (int j = 1; j < k; j++) 70 // 如果当前传入的第K行上的皇后放置的位置和其它皇后一个对角线(abs(x[k]- x[j])==abs(k-j)或一个直线上(x[j] == x[k]) 71 if (Math.abs(x[k] - x[j]) == Math.abs(k - j) || (x[j] == x[k])) 72 return false; 73 return true; 74 } 75 76 public static void main(String[] args) 77 { 78 System.out.print("请输入皇后数:"); 79 Scanner scan=new Scanner(System.in); 80 int n=scan.nextInt(); 81 System.out.println(" 棋盘布置方案:"); 82 N_Queens n_queens = new N_Queens(n); 83 scan.close(); 84 System.out.print("总共解数为:"+ n_queens.methodNum); 85 } 86 }
作者:耑新新,发布于 博客园
转载请注明出处,欢迎邮件交流:zhuanxinxin@aliyun.com