问题:
在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法?
分析:
乍一看n*n似乎需要一个二维数组,实际上一个一维数组就足够了,例如rec[x]=y;
其中x就是横坐标,y就是纵坐标。
这边讲解的是中规中矩的回溯法。
回溯法:步步深入试探,若无果,返回上一级重新选择,这就是回溯法。(感觉像深搜的剪枝)
大致思路:
就是回溯的思路,只不过在判定条件上比较麻烦的是需要判定斜线上是否相同。
左斜线:每一个点的x坐标和y坐标相减的值都相同,
右斜线:每一个点的x坐标和y坐标相加的值相同,
如下图:(虽然是手敲的)
1,1 1,2 1,3
2,1 2,2 2,3
3,1 3,2 3,3
左斜线:1-1=2-2=3-3
右斜线:1+3=2+2=3+1
行:因为是一维数组下标不可能相同所以不可能在同一行,
列:是否在同一列只需要判断每一个下标对应的值是否相等就行了。
有了这个结论我们就可以以此写判断条件
以下是代码
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;
public class _15dfsn皇后问题 {
static int[] rec;//一维数组
static int row;//行
static int cnt;//列
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);//
row = sc.nextInt();
rec = new int[row];
cnt = 0;
dfs(0);
System.out.println(cnt);//输出结果
}
static void dfs(int r) {
if (r == row) { //求出一组解,cnt+1
cnt++;
return;
}
for (int col = 0; col < row; col++) {//试探每一个列是否能否放置皇后
boolean ok = true;
for (int j = 0; j < r; j++) {//遍历之前每一个皇后位置
if (rec[j] == col || rec[j] + j == col + r || rec[j] - j == col - r) {//是否和当前皇后在同一斜线或者同一列
ok = false;
break;
}
}
if (ok) {//如果当前点可放置,则继续下一个节点的探查
rec[r] = col;//记录列
dfs(r + 1);
rec[r] = 0;//可写可不写反正开始新的一组判定时会重新赋值
}
}
}
}