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