八皇后问题

 

 

昨天学习了下八皇后问题的递归写法,觉得很有意思,贴上来小结一下。这个问题可以通过二维数组的穷举来计算结果,但是用一维数组看起来更巧妙,代码也很简洁。

数组的0下标表示第0行,1下标表示第1行......依次类推。

按照一般穷举的思路,我们从棋盘的[0,0]坐标开始摆放皇后,这个坐标可以通过arr[0] = 0 这种方式来表达,下标0表示存在第0行,值0表示在第0列,将本来用二维数组表示的期盼简化成一维数组。

1.第一个皇后存在0列,固定好这个位置,开始循环遍历,寻找第二个皇后的位置,在judge方法中,对后续摆放的皇后的位置进行判断,是否可行,判断的方式是:

 

 前面的表达式判断是否在同一行,后面的是判断他们是否在同一斜线上,如果在的话,x轴的坐标差长度等于y轴坐标差长度

2.通过上面的判断,我们在遍历中判断传入的列坐标是否可行,如果可以,递归进入n+1,寻找下一个皇后的位置

3.重复1,2的过程,直到:

执行到n=8,说明put(7)已经结束,走到了put(7)的出口,但是put(7)结束不表示程序的结束,put(6)的for循环中,i++,再执行下一轮put(7),直到put(6)的for循环遍历结束,又回溯到put(6)中,不断重复这个过程直到回溯到put(0),将put(0)中循环遍历结束程序才终止。

代码如下:

 1 package com.vi.test;
 2 
 3 import java.util.Arrays;
 4 
 5 //  八皇后问题
 6 public class TestRecurision {
 7     private static final Integer[] arr = new Integer[8];
 8     private static int count = 0;
 9 
10     //  n表示第几个皇后,在主方法中传入一个0,说明是从第0个皇后开始
11     private static void put(int n) {
12         if (n == 8) {
13             count++;
14             print();
15             //  已经轮到第9个皇后,说明前面的都已经放好了,当前这轮游戏结束,开始下一轮,直到所有的排法都被遍历,程序在这里退出
16             return;
17         }
18         //  循环遍历存放位置,判断是否可行,如不可行,换下个位置
19         for (int i = 0; i < 8; i++) {
20             arr[n] = i;
21             if (judge(n)) {
22                 put(n + 1);
23             }
24         }
25     }
26 
27     //  判断在当前行第n列摆放皇后是否可行
28     private static boolean judge(int n) {
29         for (int i = n - 1; i >= 0; i--) {
30             //  如果这个皇后摆在和前面元素同一列或者同一条斜线上,则说明当前位置不可行
31             if (arr[n] == arr[i] || Math.abs(i - n) == Math.abs(arr[i] - arr[n])) {
32                 return false;
33             }
34         }
35         return true;
36     }
37 
38     //  打印皇后组合
39     private static void print() {
40         System.out.println(Arrays.asList(arr));
41     }
42 
43     public static void main(String[] args) {
44         put(0);
45         System.out.println("共有" + count + "种解法");
46     }
47 
48 }

最终程序的结果:

 

posted on 2020-10-14 20:39  nameless_vi  阅读(158)  评论(0编辑  收藏  举报

导航