8皇后问题
最近在学习数据结构中的递归算法,并且使用递归思想学习了著名的8皇后问题。
-
先谈谈自己对递归的理解吧。递归算法就是程序不断的调用自身的过程,递归的过程中,一定要注意两点:1.一定要有终止递归的条件;2.一定要不断的逼近递归的终止条件。程序每次调用自身,就会在调用处重新开辟一个栈空间,如果调用的参数是基本数据类型,那么这个栈空间会将参数作为局部变量存放,只供当前栈空间使用。如果调用的参数是引用数据类型,那么会将该参数存放在堆空间中成为成员变量供整个程序使用。当达到递归终止条件时,会将结果返回给上一次递归的位置,直至返回给第一次递归的位置,然后继续代码继续向下执行。
-
8皇后问题的规则是:在一个8*8大小的棋盘上,每行放置一个皇后,一共放置8个皇后,这8个皇后之间要保证:1.不在同一列;2.不在同一斜线、反斜线上。问共有多少种摆法?
-
8皇后问题的解决思路:
1.将第一个皇后放在第一行第一列上;
2.之后将每个皇后从下一行的第一列开始放置,然后判断是否与之前的皇后有冲突;
3.如果有冲突,就放在下一列上,继续判断;
4.如果当前皇后在8列上都与之前的皇后有冲突,就将上一个皇后往所处行的下一列放置(回溯);
5.反复执行2-4步,直至开始放置第9个皇后时,终止递归,跳出方法; -
8皇后问题的第一种解决方式是定义一个88的二维数组模拟棋盘,规定88棋盘没有放置皇后的位置全部为0,放置皇后的位置全部为1。
package com.recursion;
/*
* 使用二维数组实现8皇后问题
* 默认棋盘初始化全为0,每放一个皇后,该位置置为1
*/
public class Queen8Demo3 {
// 表示8*8棋盘
static int[][] array = new int[8][8];
// 计数
static int count = 0;
public static void main(String[] args) {
put(0);
System.out.printf("一共有%d种解法\n", count);
}
// 摆放皇后
public static void put(int n) {
if (n == 8) {
System.out.println("第" + count + "种解法");
print();
return;
}
for (int i = 0; i < 8; i++) {
//每次将当前行上的皇后清空
for (int j = 0; j < 8; j++) {
array[n][j] = 0;
}
// 如果不冲突
if (judge(n, i)) {
// 每次先将第n个皇后放在第n行的第一列
array[n][i] = 1;
put(n + 1);
}
}
}
// 每次放一个皇后,就判断是否与之前的皇后在同一列或者同一斜线
public static boolean judge(int n, int y) {
// 判断是否在同一列上
for (int i = n; i >= 0; i--) {
if (array[i][y] == 1) {
return false;
}
}
// 判断从右上到左下的斜线方向
for (int i = n, j = y; i >= 0 && j >= 0; i--, j--) {
if (array[i][j] == 1) {
return false;
}
}
// 判断左上到右下的斜线方向
for (int i = n, j = y; i >= 0 && j < array.length; i--, j++) {
if (array[i][j] == 1) {
return false;
}
}
return true;
}
// 打印棋盘
public static void print() {
count++;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
}
- 8皇后问题的第二种解决方式是通过创建一个长度为8的一维数组,该数组的下标表示棋盘的第几行,也代表第几个皇后,数组中每个位置上的具体数组表示皇后放在该行的第几列
package com.recursion;
/*
* 8皇后问题,用一维数组实现,下标表示第几行,也就是第几个皇后,值代表第几列
*/
public class Queen8Demo2 {
//创建一个长度为8的数组,用来存放皇后的位置
static int[] array=new int[8];
//计数
static int count=0;
public static void main(String[] args) {
put(0);
System.out.printf("共有%d种摆法\n",count);
}
//摆放皇后,n表示摆放第n+1个皇后
public static void put(int n) {
//如果n=8,说明是第九个皇后,也就是前8个皇后已经摆好了
if(n==8) {
print();
return;
}
//否则,现在开始摆放皇后
//从每行的第一列开始放皇后,每放一个皇后就要判断是否与已经放好的皇后冲突
for (int i = 0; i < 8; i++) {
//先把皇后放在第1列上
array[n]=i;
//如果不冲突,就可以摆放下一个皇后了,即再调用put()
if (!judge(n)) {
put(n+1);
}
//如果第i个位置不符合,那就判断下一下个位置
//如果这一行的8个位置都不符合,那就重新摆放上一行的皇后
}
}
//判断每次摆放的位置是否在同一列或者在同一斜线上
public static boolean judge(int n) {
//每次摆放的时候需要跟前面的n-1个皇后比较
for (int i = 0; i < n; i++) {
//如果在同一列,或者在同一斜线上,那就返回true
if(array[i]==array[n]||Math.abs(n-i)==Math.abs(array[n]-array[i])) {
return true;
}
}
return false;
}
//打印数组
public static void print() {
count++;
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
System.out.println();
}
}
以上是自己对递归思想和8皇后问题的理解,如有错误之处还望指出,我会及时改正。