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

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

1.什么是八皇后问题

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

在这里插入图片描述

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

2.解法分析

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

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

参考文献2有张图,比较详细的用图描述了上面的过程,贴出来大家参考。下面图描述的是4皇后的回溯过程,原理跟8皇后是一致的。
在这里插入图片描述

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<N; row++) {
                for(int col=0; col<N; col++) {
                    System.out.print(boards[row][col] + " ");
                }
                System.out.println();
            }
            System.out.println();
        } else {
            for(int i=0; i<N; i++) {
                if (check(k, i)) {
                    boards[k][i] = 1;
                    putQueQue(k+1);
                    boards[k][i] = 0;
                }
            }
        }
    }

    public static boolean check(int row, int column) {
        for(int i=0; i<row; i++) {
            if (boards[i][column] == 1) {
                return false;
            }
        }

        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<N; m--, n++) {
            if (boards[m][n] == 1) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        putQueQue(0);
        System.out.println("result is: " + result);
    }
}

代码输出结果:

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<N; row++) {
                for(int col=0; col<N; col++) {
                    System.out.print(boards[row][col] + " ");
                }
                System.out.println();
            }

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

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

        for(int i=0; i<row; i++) {
            if (boards[i][column] == 1) {
                return false;
            }
        }

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

        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<N; m--, n++) {
            if (boards[m][n] == 1) {
                return false;
            }
        }

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

如果该位置能放置皇后,则将棋盘中该位置置为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

《电路分析简明教程》是一本电子工程领域的重要教材,内容涵盖了电路理论、分析方法和求解技巧等方面的知识。这本书的PDF版非常实用,可以为电路分析提供必要的指导和帮助。 《电路分析简明教程》的PDF版本以简明易懂的方式呈现了电路分析的基本概念和原理,先从电流电压的基础概念入手,逐渐引入电路元件的基本特性和基本量参数,如电阻、电容和电感等。通过深入浅出的讲解,读者能够快速掌握电路分析的基本方法和技巧。 该书详细介绍了直流电路和交流电路的分析方法,包括各种线性电路的定律、电路等效变换以及求解方程的常用技巧。同时,还讲解了常见电路元件的特性曲线及其对电路行为的影响,为读者提供了理论与实践相结合的学习体验。 除了理论知识,该书还提供了多个电路例题和习题,供读者进行实践和巩固所学知识。通过反复练习,读者可以掌握电路分析技能,并在解决实际问题时能够熟练运用所学知识。 总之,《电路分析简明教程》PDF版本是一本对电子工程师和电路爱好者来说都非常有价值的教材。它以简明易懂的方式讲解了电路分析的基本概念和原理,帮助读者快速掌握电路分析的方法和技巧。读者可以通过实践和习题巩固所学知识,并将其运用到实际问题中。无论是初学者还是已有一定基础的人群,都可以从中受益匪浅。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值