解题思路:
下面是用递归的深度优先搜索求解n皇后问题的算法描述:
这里用一个N×N的矩阵来表示棋盘,但是我们不需要定义这样的数组,只要心中有N×N的棋盘即可。
1.算法开始:
当前行设为第一行,当前列设为第一列,从第一行第一列开始搜索,即只能让皇后从第一行放到第n行。
这样在每次判断是否满足情况时我们不用去判断是否皇后在相同行。
我们只用判断之前的 1 到 k - 1个皇后的位置和当前第k个皇后的位置是否属于同一列或者斜线,判断是否同一列。
2.判断边界条件:
在当前行,当前列的位置上判断是否满足条件(即保证经过这一点的行,列与斜线上都没有两个皇后),若不满足,跳到第 5 步,即不符合边界条件。
不符合边界条件,不只是跳出了搜索范围,剪枝也可以从这里开始,比如这里不满足条件,向下继续搜索也不会再有结果。
这可以理解为超出边界的剪枝,我们的边界只得可能存在解的范围,这里已经超出有解的范围,必然要被踢出。
判断条件:
我们用数组 x[k] = i 来表示第 k 个皇后在第 k 行第 i 列,不用考虑是否在同一行的问题,只用判断之前的 1 到 k - 1个皇后的位置与当前的第 k 个皇后是否在同列或同一斜线。
同列条件: x[i] == x[k]; 同一斜线斜率相同:abs(x[k] - x[i]) == abs(k-i);
3.搜索方法:
判断边界条件,搜索下一个皇后的位置。
4.pd2函数停止条件:
如果当搜索到第N+1 行的时候,即代表前N 行已经搜索完了,所以这个时候正好求出了一个解,记录加一,返回上一层搜索。
5.在当前位置上不满足条件的情形,进行回溯。
参考代码:
import java.util.Scanner; public class Main { static int n;//皇后数 static int sum;//方案数 static int[] x; // 判断是否符合放置条件 static boolean pd1(int k) { //k为行号,x[k]为列号 //将k行的皇后分别与上面的进行比对,看是否同线 for (int i = 1; i < k; i++) { //在同一斜线上,直线的斜率为+-1 if (Math.abs(k - i) == Math.abs(x[k] - x[i])) return false; //在同一列 else if (x[k] == x[i]) return false; } return true; } //判断是否摆放完成 static boolean pd2(int k) { //行号已经出界,摆放完成,return true;方案数加一 if (k > n) sum++; else return false; return true; } static void DFS(int k) { //摆放完成,返回上一层 if (pd2(k)) { //输出前3种方法 if (sum <= 3) { for (int i = 1; i <= n; i++) { System.out.print(x[i] + " "); } System.out.println(); } return; } else { for (int i = 1; i <= n; i++) { //将第k个(行)皇后放在第i列上 x[k] = i; //能摆放这个位置 if (pd1(k)) { //寻找下一个位置 DFS(k + 1); } else { //找不到列号往后移动 continue; } } } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); n = scanner.nextInt(); x = new int[n + 1]; DFS(1);//从第一个开始放 System.out.print(sum); } }
0.0分
2 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复