思路
1.八个皇后在8*8棋盘中不能互相攻击,即不能在同一行同一列和同一斜线上
2. 使用暴力破解算法,进行穷举法,每摆放一个皇后判断,是否与之前摆放在皇后产生冲突(不能互相攻击)
3. 若产生互相攻击则尝试,下一个一位置。若同行的位置的测试完不行则,进行回溯,到上一行,进行下一个位置的摆放。
4. 当摆放到第八个皇后时,表示一种解法。
思路2
1.用一个一维数组模拟8*8棋盘。数组的下标表示,行,值标时列。
数组下标与要摆放的皇后相等
2. 判断是否冲突方法。只需判断列和斜线上是否有皇后。行不需要判断,因为每次放皇后都是从下一行开始放
3. 因为列是用数组所存value值所表示的,只有数组中值不存在相等的即列吧相等。
4.而斜线判定是|行相减的绝对值|==|列相将的绝对值|时,皇后能互相攻击。(若两个皇后在同一斜线上,两个皇后进行连续,会形成一个等腰三角形,即判断倆边是否相等即可)
5. 当n=8时表示正在,递归到第九,表示第八已经摆放完毕,此时输出数组,count++;return退出结束方法。
class sss{
public static void main(String[] args) {
sss s=new sss();
s.run(0);
System.out.println(s.count);
}
//一维数组 模拟棋盘
int[] board=new int[8];
//计数器 计算摆放的解法个数
int count=0;
//皇后的摆放方法
/**
*
* @param n 摆放 第n个皇后
*/
public void run(int n){
//判断是否摆放到第8个皇后。 递归结束条件
if(n==8){
//计算器自增
count++;
//输出数组内容
for (int i = 0; i <board.length ; i++) {
System.out.print(board[i]+" ");
}
//换行
System.out.println();
//return 结束方法
return;
}
//循环摆放皇后 i从0开始 board.length 8
for (int i =0; i <board.length ; i++) {
//board[n] 索引n表示 第n个皇后 同时表示第n行
// 先将皇后放入,然后再进行判断是否相互攻击
board[n]=i;
//判断皇后是否互相攻击 不相互攻击则递归调用 ,放下一个皇后
if(pan(n)){
//递归调用
run(n+1);
}
}
}
/**
*
* @param n 现在摆放第几个皇后 摆放第几 n范围 0-7
* @return 放回TRUE 表示,未冲突, 返回FALSE表示冲突
*/
public boolean pan(int n){
//从第一个皇后 遍历到 第n个皇后节点
// 皇后 不能在 同一行 ,同一列 ,同一斜线上
/* 同一列 ,判断 数组中的值是否相同
同一行,因为数组的索引下标代表每一行,每次摆放皇后都是从下一行进行摆放
所以不需要进行判断。
同一斜线上,当两个皇后在同一斜线上时,
* * * * * * * * 两个皇后进行连线,与棋盘两条边。形成一个等腰三角形
* * * * * * * * 也就是说,只有两条边相等,
* * * * * * * * 1 = board[0] =3 0 ,3
* * * * * * * * 2 = board[2] =6 2, 6
* * * * * * * *
* 3 * * * 2 * * 5-3==2-0 绝对值相等 皇后在同一斜线上
* * * * * * * * 1-3==2-0 绝对值相等
* * * 1 * * * *
* */
for (int i = 0; i <n ; i++) {
// 不在同一列
if(board[i]==board[n]){
return false;
}
// 斜线 长==宽 ---> 列相减==行相减 就在同一斜线上
if(Math.abs(board[i]-board[n])==Math.abs(i-n)){
return false;
}
}
return true;
}
}
run方法
- 摆放从第一个皇后开始(从0开始),board【0】表示从第一行开始。
- 循环遍历i(0-7),赋值给board【n】=i,然后进行判断皇后的摆放是否符合要求,若符号要求run(n+1)递归调用,n+1下一行,又进行循环遍历进行赋值然后判断,若一直判定为TRUE直到n=8是就会结束方法,放回到n=7,进行尝试摆放,在放回第n=6进行回溯尝试。
public void run(int n)
//循环摆放皇后 i从0开始 board.length 8
for (int i =0; i <board.length ; i++) {
//board[n] 索引n表示 第n个皇后 同时表示第n行
// 先将皇后放入,然后再进行判断是否相互攻击
board[n]=i;
//判断皇后是否互相攻击 不相互攻击则递归调用 ,放下一个皇后
if(pan(n)){
//递归调用
run(n+1);
}
}
- 八皇后回溯算法,在进行皇后的摆放时,若尝试完都不合法,会返回上一个位置,进行回溯,进行下一个位置的尝试。回溯算法:在遇到不符合条件时,会回退上一步进行尝试。