回溯法解决八皇后问题

八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

八皇后问题最早是由国际国际象棋棋手马克斯·贝瑟尔于1848年提出。之后陆续有数学家对其进行研究,其中包括高斯康托,并且将其推广为更一般的n皇后摆放问题。八皇后问题的第一个解是在1850年由弗朗兹·诺克给出的。诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。

艾兹格·迪杰斯特拉在1972年用这个问题为例来说明他所谓结构性编程的能力。

八皇后问题在1990年代初期的著名电子游戏第七访客NDS平台的著名电子游戏雷顿教授与不可思议的小镇中都有出现。

 

以上内容来自维基百科。

解决八皇后问题的思路:

1、用数组queues表示八个皇后的位置,下标为列,值为行。这样初始时八个皇后就在不同的列,问题变成了给八个皇后行的排列组合。

2、找到第i行棋盘上的可以放置皇后的方格,即行号和列号满足3就可以放置皇后。检查第j列,满足放置条件进入4,否则进入5。

3、

  a.方格与已经标记的皇后不在同一列,不在同一行。

  b.方格与已经标记的皇后不在同一正斜线,不在同一反斜线。

4、标记皇后为queues[i]=j,如果此时所有行都已经放置皇后,即行号i = 7,则放置方法总数加1,否则 将i = i+1,返回步骤2。

5、将j = j+1,返回步骤2。

 

代码如下:

package com.smikevon.basic.interview;

/**
 * Created by fengxiao on 15-2-27.
 */
public class EightQueen {
    
    private static final int CHESS_SIZE = 8;

    //数组下标表示列,数组对应的值表示行
    private static int[] queens = new int[CHESS_SIZE];
    
    private static int sum;
    
    public static void main(String[] args){
        
        //初始化为一个不存在的行
        for(int i=0;i<CHESS_SIZE;i++){
            //保证列列不受初始值影响
            queens[i] = 10000;
        }
        
        //查找将哪个皇后放在第0行
        count(queens,0);
        System.out.println("total:"+sum);
    }
    
    /**
     * 找出一个皇后放在第row行
     */
    public static  void count(int[] queens, int row){
        
        for(int i=0;i<CHESS_SIZE;i++){
            queens[row]=i;
            if(checkLegal(row)){
                if(row == CHESS_SIZE-1){
                    printChess();
                    sum++;
                }else{
                    count(queens,row+1);
                }
            }
        }
        
    }

    /**
     * 和第row行之前已经放置好的皇后进行比较,查看是否是合规位置
     */
    public static boolean checkLegal(int row){
        for(int i=0;i<row;i++){
            if(queens[i]-queens[row] == row-i || row-i ==queens[row]-queens[i] || queens[row]==queens[i]){
                return false;
            }
        }
        return true;
    }

    /**
     * 打印出棋局
     */
    public static void printChess(){
        System.out.println();
        for(int i=0;i<CHESS_SIZE;i++){
            for(int j=0;j<CHESS_SIZE;j++){
                if(queens[i] != j){
                    System.out.print("* ");
                }else{
                    System.out.print("Q ");
                }
            }
            System.out.println();
        }
        
    }

}

 

打印结果:

* * * * * Q * * 
* * * Q * * * * 
Q * * * * * * * 
* * * * Q * * * 
* * * * * * * Q 
* Q * * * * * * 
* * * * * * Q * 
* * Q * * * * * 

* * * * * Q * * 
* * * Q * * * * 
* Q * * * * * * 
* * * * * * * Q 
* * * * Q * * * 
* * * * * * Q * 
Q * * * * * * * 
* * Q * * * * * 

* * * * * Q * * 
* * * Q * * * * 
* * * * * * Q * 
Q * * * * * * * 
* * Q * * * * * 
* * * * Q * * * 
* Q * * * * * * 
* * * * * * * Q 

* * * * * Q * * 
* * * Q * * * * 
* * * * * * Q * 
Q * * * * * * * 
* * * * * * * Q 
* Q * * * * * * 
* * * * Q * * * 
* * Q * * * * * 

 

posted @ 2015-02-27 17:02  星火照天明  阅读(453)  评论(0编辑  收藏  举报