1)
八皇后及N皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。
请编程实现八皇后问题,并把92种解的前三种解输出到屏幕(8*8的二维矩阵,Q代表皇后,X代表空)。并把此问题的求解过程延伸到N皇后问题。
思路:采用回溯思想,遍历所有行,从矩阵的第一行第一列开始查找可以放置皇后的安全位置,若找到安全位置则往下一行查找安全位置,直至遍历结束。若当前行的所有列均不安全,则回溯到上一行,从上一行的下一列再继续查找。。。
输出的解以8皇后问题为例,N皇后问题只需修改皇后的数量。用java实现,代码如下:
- public class Queens {
- int num ; // 皇后数量
- int [] queenArray ; // 存储可行方案的皇后们的位置
- int count = 0; // 解决方案的数量
- /**
- * 初始化
- * @param num 皇后的数量
- */
- public Queens(int num){
- this.num = num;
- queenArray = new int[num];
- }
- /**
- * 判断当前行放置了皇后是否会与前面几行放置的皇后们发生冲突
- * @param row
- * @return
- */
- public boolean isSafe(int row){
- for(int r=0; r<row; r++){
- // 发生冲突的条件:皇后们在同一行(此处不用判断是否同一行)、同一列、
- if(queenArray[row] == queenArray[r] ||
- // 同一对角线(斜率=(y2-y1)/(x2-x1)= +1或-1 )
- Math.abs(queenArray[row]-queenArray[r]) == Math.abs(row-r))
- return false;
- }
- return true;
- }
- /**
- * 回溯查找解决n皇后问题的方案
- * @param row 第几行
- */
- public void backTrack(int row){
- // 找到一个放置所有皇后而不发生冲突的方案,打印出来
- if(row == num){
- count++;
- print();
- return;
- }
- // 未遍历到最后一行,查找当前行的某个适合放置皇后的列
- for(int col = 0; col < num; col++)
- {
- queenArray[row] = col;
- //当前行的某个列适合放置皇后,往下一行查找
- if(isSafe(row))
- backTrack(row+1);
- }
- }
- public void print(){
- System.out.println("方案 "+count+":");
- for(int i=0; i<num; i++){
- for(int j=0; j<num; j++){
- if(j == queenArray[i])
- System.out.print("Q ");
- else
- System.out.print("X ");
- }
- System.out.println();
- }
- System.out.println("\n");
- }
- public static void main(String[] args) {
- Queens queens = new Queens(8);
- queens.backTrack(0);
- }
- }