八皇后问题

来源:互联网 发布:linux 70秒漏洞 编辑:程序博客网 时间:2024/06/03 22:38

问题描述

八皇后问题是一个以国际象棋为背景的问题:如何能够在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);    }}
0 0