数据结构算法-八皇后问题

递归-八皇后问题(回溯算法)

八皇后问题介绍

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法(92)

 

 

八皇后问题算法思路分析

 

 

  1. 第一个皇后先放第一行第一列
  2. 第二个皇后放在第二行第一列、然后判断是否 OK, 如果不 OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
  3. 继续第三个皇后,还是第一列、第二列……直到第 8 个皇后也能放在一个不冲突的位置,算是找到了一个正确解
  4. 当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解, 全部得到.
  5. 然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4 的步骤
  6. 示意图:

 

 

    • 说明:

理论上应该创建一个二维数组来表示棋盘,但是实际上可以通过算法,用一个一维数组即可解决问题. arr[8] =

{0 , 4, 7, 5, 2, 6, 1, 3} //对应 arr 下标 表示第几行,即第几个皇后,arr[i] = val , val 表示第 i+1 个皇后,放在第 i+1

行的第 val+1 列

 

 

八皇后问题算法代码实现

复制代码
 1 package com.xuge.recursion;
 2 
 3 /**
 4  * author: yjx
 5  * Date :2022/5/2914:52
 6  **/
 7 public class Queun8 {
 8   //定义一个 max 表示共有多少个皇后
 9   int max = 8;
10   //定义数组 array, 保存皇后放置位置的结果,比如 arr = {0 , 4, 7, 5, 2, 6, 1, 3} int[] array = new int[max];
11 
12   int[] array = new int[max];
13   static int count = 0;
14   static int judgeCount = 0;
15 
16   public static void main(String[] args) {
17 //测试一把 , 8 皇后是否正确
18     Queun8 queue8 = new Queun8();
19     queue8.check(0);
20     System.out.printf("一共有%d 解法", count);
21     System.out.printf("一共判断冲突的次数%d 次", judgeCount); // 1.5w
22 
23   }
24 
25 
26   //编写一个方法,放置第 n 个皇后
27 //特别注意: check 是 每一次递归时,进入到 check 中都有
28 // for(int i = 0; i < max; i++),因此会有回溯
29   //编写一个方法,放置第n个皇后
30   private void check(int n) {
31     if (n == max) {//n==8
32       print();
33       return;
34     }
35     //依次放入皇后,并判断是否冲突
36     for (int i = 0; i < max; i++) {
37       //先把这个皇后放到该行的第一列
38       array[n] = i;
39       //判断放置第n个皇后到i列时,是否冲突
40       if (judge(n)) {//不冲突
41         //接着放n+1个皇后
42         check(n + 1);
43       }
44       //如果冲突,就继续执行 array[n] = i; 即将第 n 个皇后,放置在本行得 后移的一个位置
45 
46 
47     }
48 
49   }
50 
51   //查看当我们放置第 n 个皇后,  就去检测该皇后是否和前面已经摆放的皇后冲突
52 
53   /**
54    * @param n 表示第 n 个皇后
55    * @return
56    */
57   private boolean judge(int n) {
58     judgeCount++;
59     for (int i = 0; i < n; i++) {
60       // 说明
61       //1. array[i] == array[n]    表示判断 第 n 个皇后是否和前面的 n-1 个皇后在同一列
62       //2. Math.abs(n-i) == Math.abs(array[n] - array[i]) 表示判断第 n 个皇后是否和第 i 皇后是否在同一斜线
63       // n = 1放置第 2 列 1 n = 1 array[1] = 1
64       //Math.abs(1-0) == 1
65       //Math.abs(array[n] - array[i]) = Math.abs(1-0) = 1
66       //3. 判断是否在同一行, 没有必要,n 每次都在递增
67       if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
68         return false;
69 
70       }
71     }
72     return true;
73   }
74 
75   public void print() {
76     count++;
77     for (int i = 0; i < array.length; i++) {
78       System.out.print(array[i] + "\t");
79     }
80     System.out.println();
81   }
82 }
复制代码

 

 

posted @   xugeA  阅读(134)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示