八皇后问题(递归解法)

eightqueens
八皇后问题,即在一个8*8的棋盘上放8个皇后,使得这8个皇后无法互相攻击( 任意2个皇后不能处于同一行,同一列或是对角线上),输出所有可能的摆放情况。
Write an algorithm to print all ways of arranging eight queens on a chess board so that none of them share the same row, column or diagonal.

八皇后是个经典的问题,如果每个格子都去考虑放皇后与否,一共有2的64次方 种可能,所以不是好方法。

因为每行只能有一个皇后, 所以可以不考虑行,只是用一个一维数组来表示皇后在行上的位置就可以了。
即第1次考虑把皇后放在第1行的某个位置, 第2次放的时候就不用去放在第一行了,因为这样放皇后间是可以互相攻击的。
第2次就考虑把皇后放在第2行的某个位置,第3次考虑把皇后放在第3行的某个位置, 这样依次去递归。
每计算1行,递归一次,每次递归里面考虑8列, 即对每一行皇后有8个可能的位置可以放。
找到一个与前面行的皇后都不会互相攻击的位置, 然后再递归进入下一行。找到一组可行解即可输出,然后程序回溯去找下一组可靠解。

用一个一维数组来表示皇后在行上的位置(也就是列),比如queens[r]=c表示, 第r行的皇后放在第c列。如果当前行是x,皇后放在queens[x]列。
一共有8列,所以我们要让queens[r]依次取第0列,第1列,第2列……一直到第7列, 每取一次考虑皇后放的位置会不会和前面已经放了的皇后有冲突。
也就是说避免同行,同列,对角线。
由于已经不会同行了,所以不用考虑这一点。
同列:queens[r]==queens[r1];
同对角线有两种可能,即主对角线方向和副对角线方向。主对角线方向满足,行之差等于列之差:r-r1==queens[r]-queens[r1]; 副对角线方向满足,行之差等于列之差的相反数:r-r1==queens[r1]-queens[r]。
只有满足了当前皇后和前面所有的皇后都不会互相攻击的时候,才能进入下一级递归.

Java代码:

public class EightQueens{
    //棋盘容量
    public static final int SIZE=8;
    //表示皇后在行上位置的一维数组
    private int[] queens=new int[SIZE];
    //方案数目
    private int answers=0;

    public EightQueens(){
        search(0);
        System.out.println("There are "+answers+" methods");
    }
    //打印解法,#代表放置皇后,o代表空
    public void print(){
        System.out.println("method"+(answers+1));
        for(int r=0;r<SIZE;r++){
            for(int column=0;column<SIZE;column++){
                if(column==queens[r]) 
                    System.out.print("#");
                else 
                    System.out.print("o");
            }
            System.out.println();
        }
        System.out.println();
    }
    //为指定一行寻找解法
    public void search(int row){
        if(row==SIZE){
            print();
            ++answers;
            return;
        }

        for(int r=0;r<SIZE;r++){
            queens[row]=r;
            boolean ok=true;
            //确保没有同一列,主对角线,副对角线
            for(int r1=0;r1<row;r1++)
                if(queens[row]==queens[r1]
            ||row-r1==queens[row]-queens[r1]
            ||row-r1==queens[r1]-queens[row]){
                ok=false;
                break;
            }
            //递归查找
            if(ok) search(row+1);
        }
    }

    public static void main(String[] args){
        EightQueens eq=new EightQueens();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值