史上最简明八皇后问题分析与套路总结

项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

1.什么是八皇后问题

八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当n = 1或n ≥ 4时问题有解。(问题描述来自参考文献1)

史上最简明八皇后问题分析与套路总结_第1张图片

数学王子高斯当年花费了无数心血,最后计算认为八皇后问题有76种解法,现在我们通过计算机模拟可以轻松计算出八皇后问题的真正解法有92种。能让高斯栽跟头的问题,可想而知计算的复杂性与难度。

2.解法分析

高斯将八皇后的解法推导出76种,已经算是非常厉害了。这不能怨高斯,而是八皇后的计算复杂度确实太高。
该问题的整体思路还是暴力解法
1.先列出所有可能的皇后摆放方式。
2.再检查该种摆放方式是否符合要求。

具体的执行过程如下:
先将第一个皇后放在第一行第一列,然后将第二个皇后放在第二行第一列,判断该种摆法是否符合要求。很明显这样摆不行,有两个皇后会在同一列。再将第二个皇后放在第二行第二列,这样也不行,两个皇后会在一条斜线上。将第二个皇后放在第二行第三列,这样满足当前条件。
目前已经有两个皇后满足条件,接下来放第三个,还是从第三行第一列开始放置,不满足条件再放第二列,第三列…一直到第8个皇后也能放在一个不冲突的位置,此时找到一个符合要求的解。
然后我们开始回溯,将第一个皇后放在第一行第二列,后面的就继续按上面的方式循环,一直到回溯完毕,找出所有符合条件的解为止。

参考文献2有张图,比较详细的用图描述了上面的过程,贴出来大家参考。下面图描述的是4皇后的回溯过程,原理跟8皇后是一致的。
史上最简明八皇后问题分析与套路总结_第2张图片

3.代码实现

上面原理分析完毕,接下来看代码实现。

public class NQueueV2 {

    public static int N = 4;
    public static int[][] boards = new int[N][N];

    public static int result = 0;

    public static void putQueQue(int k) {
        if (k == N) {
            result++;
            for(int row=0; row=0 && n >= 0; m--, n--) {
            if (boards[m][n] == 1) {
                return false;
            }
        }

        for(int m=row-1, n=column+1; m>=0 && n

代码输出结果:

0 1 0 0 
0 0 0 1 
1 0 0 0 
0 0 1 0 

0 0 1 0 
1 0 0 0 
0 0 0 1 
0 1 0 0 

result is: 2

上面的代码,为了方便输出最后结果,模拟的是4皇后,8皇后只需要将N改为8即可。

board二维数组,模拟的是棋盘,初始状态均为0,表示该位置没有放置皇后。如果该位置设为1,表明该位置有皇后。

k表示放置的皇后个数。如果k==N,说明N个皇后都被放置完毕,此时得到一个有效解。

            for(int row=0; row

该部分代码输出有效解的状态,数组为1的位置表示该位置放置了皇后。

else部分代码,i表示的是第i列,check(k, i)方法表示的是在(k, i)这个位置放置皇后是否合法

        for(int i=0; i

这部分代码,表示两个皇后不能放置在同一列。

        for(int m=row-1, n=column-1; m>=0 && n >= 0; m--, n--) {
            if (boards[m][n] == 1) {
                return false;
            }
        }

这部分代码,表示该皇后的左斜线部分不能有皇后。

        for(int m=row-1, n=column+1; m>=0 && n

这部分代码,表示该皇后的右斜线部分不能有皇后。

如果该位置能放置皇后,则将棋盘中该位置置为1,接下来往下一行放皇后putQueQue(k+1)。同时,在回溯的时候,需要将该位置置为0。

4.套路总结

所以看上去很复杂的八皇后问题,对着图,再对着代码分析,是不是感觉没那么难了?
本质还是经典回溯算法的使用,跟前面我们讲到的排列组合类似。当了解完整个过程以后,回溯的难度甚至比排列组合还小!
史上最全排列组合算法详解以及套路总结一文搞定

参考文献

1.https://zh.wikipedia.org/wiki/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98
2.https://juejin.cn/post/6844903798926753805

你可能感兴趣的:(High,Freq,Interview,八皇后,回溯,遍历,DFS)