7.八皇后问题
八皇后问题算法解题思路
1.第一个皇后先放到第一行第一列。
2.第二个皇后放在第二行第一列,然后判断是否ok。,如果不ok,继续放在第二列、第三列,依次把所有列都放完,找到一个合适的。
3.继续放第三个皇后,还是第一列、第二列....直到第八个皇后也能放在一个不冲突的位置上。算是找到一个正确解。
4.当得到一个正确解时,就开始回溯,北京第一个皇后放在第一列的所有正确解嗯全部拿到。
5.然后开始回头继续第一个皇后放入第二列。,后面继续循环,执行1234步骤。
说明:
理论上应该创建一个二维数组表示棋盘,但实际上可以通过算法用一个一维数组即可解决问题。
arr[8]={0,4,7,5,2,6,1,3}对应的arr下标表示第几行,即第几个皇后,arr[i]=val,val表示第i+1个皇后,放在i+1行的第val+1列
package cn.com.linkedList;
/**
* 8皇后问题
*/
public class EightEmpresses {
//设置棋盘的规格
private static final int QUEEN = 8;
//设置棋盘
private static final int[][] CHECKERBOARD = new int[QUEEN][QUEEN];
//第几种解法
private static int count = 0;
public static void show() {
System.out.println("第" + (++count) + "种解法--------");
for (int i = 0; i < CHECKERBOARD.length; i++) {
for (int j = 0; j < CHECKERBOARD[i].length; j++) {
System.out.print(CHECKERBOARD[i][j] + " ");
}
System.out.println();
}
}
/**
* 检查这个点是否可以存放数据
*
* @param row 行
* @param col 列
* @return 是否可以存放数据
*/
public static boolean check(int row, int col) {
//1.检查上方是否有皇后
for (int i = row - 1; i >= 0; i--) {
if (CHECKERBOARD[i][col] == 1) {
return false;
}
}
//2.判断左上方是否有值
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (CHECKERBOARD[i][j] == 1) {
return false;
}
}
//3.判断右上方是否有值
for (int i = row - 1, j = col + 1; i >= 0 && j <QUEEN; i--, j++) {
if (CHECKERBOARD[i][j] == 1) {
return false;
}
}
return true;
}
/**
* 开始从第几行开始放
*
* @param row
*/
public static void put(int row) {
//1. 从第1行开始放弃,每一列都循环一遍
for (int i = 0; i < QUEEN; i++) {
//2. 判断当前位置是否可以存放
if (check(row, i)) {
//3. 可以存放,将当前位置置为1
CHECKERBOARD[row][i]=1;
//4. 到达最后一行,输出即可!
if (row==QUEEN-1){
show();
}else{
//5. 放下一行,递归,进来又循环一遍所有列
put(row+1);
}
//重点::这里需要好好理解下,如果发现某个点导致下述的没法放了,就开始回溯,改正之前错误点位置,好好品!
CHECKERBOARD[row][i]=0;
}
}
}
public static void main(String[] args) {
put(0);
}
}
测试输出:
第1种解法--------
1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
第2种解法--------
1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0
。。。
第92种解法--------
0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0
共计92种解法
第二种解法:通过一维数组表示棋盘,如arr[i]=val,表示第i行的第val列是皇后
package cn.com.linkedList;
/**
* 8皇后问题的第二种解法
* 只用一个一维数组表示
* arr[i]=val 表示第i+1行的第val+1位置上放上皇后
*/
public class Queue8 {
//定义有多少个皇后,即多少行
private static int max = 8;
//创建一个一维数组
private static int[] array = new int[max];
//第几种解法
private static int count = 0;
public static void show() {
System.out.println("第" + (++count) + "种解法--------");
for (int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
System.out.println("\n--二位棋盘--");
for (int i=0;i<array.length;i++){
for (int j=0;j<max;j++){
if (j==array[i]){
System.out.print(1+" ");
}else{
System.out.print(0+" ");
}
}
System.out.println();
}
}
/**
* 放入第几行的皇后
*
* @param n
* @return
*/
public static boolean check(int n) {
for (int i = 0; i < n; i++) {
/*
这里比较有意思:比较和前几行皇后位置
1.比较是否再同一列:array[n] == array[i],同一列的话,这个数值会相等array[n]=val代表第n行的第val列
2.判断是否在一条斜线上:
这里需要注意的是斜线是45都斜线,即斜率为1,想象去哦盘为一个象限
表达式为:y=x+b,线上的两个点
1.y1=x1+b
2.y2=x2+b
1式减2式,发现两个点的y值差等于x值差
通过这个特性判断两个点是否在一条斜线上
*/
if (array[n] == array[i] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
public static void put(int row) {
//这里需要注意,不能是row==max-1,因为当到最后一行时,row==max-1,直接返回了,则下面的赋值就没有进行
if (row == max) {
//放到最后一行了,打印输出
show();
return;
}
//循环i列,每列都循环放一遍
for (int i = 0; i < max; i++) {
//这里式回溯的关键点,如果放置了某点,导致下述无法继续放,会回溯到这里i+1,放入到下列,继续下述循环
array[row] = i;
//可以放
if (check(row)) {
put(row + 1);
}
}
}
public static void main(String[] args) {
put(0);
}
}
测试输出:总计92种解法
第1种解法--------
0 4 7 5 2 6 1 3
--二位棋盘--
1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
第2种解法--------
0 5 7 2 6 3 1 4
--二位棋盘--
1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0
。。。
第92种解法--------
7 3 0 2 5 1 6 4
--二位棋盘--
0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0