目录
1 问题描述
把n个皇后放在一个n*n的棋盘上,使得任何两个皇后都不能相互攻击,即它们不能同行,不能同列,也不能位于同一条对角线上。
2 解决方案
本文采用全排列的方法,从n个皇后的全排列中寻找符合规则的皇后排列。
为什么这里是说 全排列呢?因为在N皇后问题中,棋盘每一行只准放一个皇后,且每一行的皇后必定要选一列。这个问题就相当于求取1~N个数字的全排列,假设全排列中一种排列方案中第一个数为x,则在棋盘第一行位置为第x列放一个皇后,其第i个位置的数y就为棋盘第i行的第y列放着一个皇后。
那么既然全排列能够得到,就要除去其中不符合条件的排列情况,此时只需要给相应排列加一个判断条件即可,符合条件的就输出这个排列,否则进入下一个排列判断。
具体代码如下:
package com.liuzhen.chapter12; public class QueenProblem { public static int count = 0; //n皇后问题中皇后摆放位置满足的限制条件,若满足则返回true,否则返回false public boolean isOk(int[] result, int step) { for(int i = 0;i < step;i++) { for(int j = i + 1;j < step;j++) { int left = i - j; int right = j - i; if(result[j] == result[i] + left || result[j] == result[i] + right) return false; } } return true; } //交换数组A中m位置和n位置上的值 public void swap(int[] A, int m, int n) { int temp = A[m]; A[m] = A[n]; A[n] = temp; } public void printResult(int[] A, int step) { if(step == A.length) { count++; for(int i = 0;i < A.length;i++) System.out.print(A[i]+" "); System.out.println(); return; } else { for(int i = step;i < A.length;i++) { swap(A, i, step); //执行回溯前的移位 if(isOk(A, step + 1)) printResult(A, step + 1); swap(A, i, step); //如果不满足条件或者已经完成一种方案,进行回溯处理 } } } public static void main(String[] args) { QueenProblem test = new QueenProblem(); int[] A = {1,2,3,4}; test.printResult(A, 0); System.out.println("符合n皇后排序条件的排序方式个数为:"+count); } }
运行结果:
2 4 1 3
3 1 4 2
符合n皇后排序条件的排序方式个数为:2
参考资料:
1.n皇后问题