八皇后问题

4 篇文章 0 订阅

问题描述

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

问题历史

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

算法原理

回溯的思想是:假设某一行为当前状态,不断检查该行所有的位置是否能放一个皇后,检索的状态有两种:
(1)先从首位开始检查,如果不能放置,接着检查该行第二个位置,依次检查下去,直到在该行找到一个可以放置一个皇后的地方,然后保存当前状态,转到下一行重复上述方法的检索。
(2)如果检查了该行所有的位置均不能放置一个皇后,说明上一行皇后放置的位置无法让所有的皇后找到自己合适的位置,因此就要回溯到上一行,重新检查该皇后位置后面的位置。

问题解法(java)

public class Queen {
    /** 皇后数量 */
    private static int num = 8;
    /** 同列是否有皇后,1表示有 */
    private static int[] column = new int[num];
    /** 左上至右下是否有皇后 */
    private static int[] lup = new int[2*num - 1];
    /** 右上至左下是否有皇后 */
    private static int[] rup = new int[2*num - 1];
    /** 解答 */
    private static int[] queen = new int[num];

    /** 序号 */
    private static int index;

    /**
     * 回溯法求解八皇后问题
     * @param i
     */
    public static void backtrack(int i) {
        if (i >= num) {
            System.out.println("num:" + ++index);
            print();
            return;
        }

        for (int j = 0; j < column.length; j++) {
            if (column[j] == 0 && lup[num - j - 1 + i] == 0 && rup[i + j] == 0) {
                queen[i] = j; //使用皇后在当前行中的序号填充当前位置
                column[j] = lup[num - j - 1 + i] = rup[i + j] = 1;
                backtrack(i + 1);
                column[j] = lup[num - j - 1 + i] = rup[i + j] = 0;
            }
        }
    }

    /**
     * 打印
     */
    public static void print(){
        for (int i = 0; i < queen.length; i++) {
            for (int j = 0; j < queen.length; j++) {
                System.out.print(queen[i] == j ? "1 " : "0 ");
            }
            System.out.println();
        }
        System.out.println();
    }

    public static void main(String[] args) {
        backtrack(0);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值