回溯法解决八皇后问题

一、八皇后问题简介

八皇后问题,一个古老而著名的问题,是回溯算法的典型案例。该问题由国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有 76 种方案。1854 年在柏林的象棋杂志上不同的作者发表了 40 种不同的解,后来有人用图论的方法解出 92 种结果。

如下图是它的一种解法

二、解决思路

采用递归回溯的方法解决。

先做如下约定

  • 我们用ways[8],这个数组存储摆放皇后的方式,其中,下标表示第几行,对应的值表示皇后所在的列
  • judge(int n) 表示判断正在放置的第n个皇后,是否会与之前摆放好的皇后存在列冲突对角线冲突(默认皇后不摆放在一行)
  • putQueen(int n) 该方法为递归的调用放置皇后的方法,若出现冲突则回溯

具体步骤:

  1. 先在第一行第一列放置第一个皇后,然后,再第二行放置第二个皇后,若与现有皇后站位不冲突,则继续在第三行放置第三个皇后......
  2. 如果发现冲突,则调整列,直到所有列均试完,若发现可以放置,则继续放置下一行,直至八个皇后均摆放完毕,如果,所有的列均与现有皇后的站位冲突则,回溯至上一行,继续遍历上一行的各列,以此类推,直到将第一行的各列均遍历完毕,就得到所有的结果。

三、代码实现

/**
 * @author ymy
 * @date 2020/5/12
 *
 * 八皇后问题:
 *      在8*8的棋盘上,放置八个皇后,
 *      要求这八个皇后的任意两个不在同一行,同一列,同一斜线
 */
public class EightQueens {

    private int queenNum = 8;//皇后数量
    private static int WAYS_NUM;
    private int [] ways=new int [8];//放置方法
    private static int judgeNums;

    /**
     * @param n 表示正在放置的第n个皇后
     * @return
     * 因为ways存储的含义就不包括同一行,所以只需要判断是否在同一列或者同一斜线即可。
     */
    public boolean jugde(int n){
        judgeNums++;
        for (int i = 0; i <n ; i++) {
            //  同一行               同一列(参考正方形对角线)
            if (ways[i]==ways[n] || Math.abs(ways[i]-ways[n])==Math.abs(i-n)){
                return false;
            }
        }
        return true;
    }

    public void print(){
        WAYS_NUM++;
        System.out.printf("这是第%d种方法:",WAYS_NUM);
        for (int a:ways){
            System.out.print(a+" ");
        }
        System.out.println();
    }

    /**
     * @param n 放置的第n个皇后
     */
    public void putQueen(int n){
        if (n==queenNum){
            print();
            return;
        }
        for (int i=0;i<queenNum;i++){
            ways[n]=i;
            if (jugde(n)){
                putQueen(n+1);
            }
        }
    }

    public static void main(String[] args) {
        EightQueens eightQueens = new EightQueens();
        eightQueens.putQueen(0);
        System.out.println("判断次数:"+judgeNums);
    }

}

四、测试结果

posted @ 2020-05-12 16:01  风和日暖  阅读(523)  评论(0编辑  收藏  举报