注意点:
斜线上不能存放多个皇后,可以用截距表示,因为所有的直线斜率都为-1或者 1 ,不会存在截距相同的直线。
截距为负数的直线,可以用n+abs(截距)处理。
另一种处理截距的方式:(更优雅)
我们可以对 5*5 正方形进行一个枚举
(0,0) (0,1) (0,2) (0,3) (0,4)
(1,0) (1,1) (1,2) (1,3) (1,4)
(2,0) (2,1) (2,2) (2,3) (2,4)
(3,0) (3,1) (3,2) (3,3) (3,4)
(4,0) (4,1) (4,2) (4,3) (4,4)
这是,坐标,可以理解为一个是x,一个是y
仔细观察,每条从右上到左下的对角线,他们横纵坐标相加的值都是相等的,对比下面图看一下
(0) (1) (2) (3) (4)
(1) (2) (3) (4) (5)
(2) (3) (4) (5) (6)
(3) (4) (5) (6) (7)
(4) (5) (6) (7) (8)
因此 x+y 为 可以来表示该条直线(k = 1)。
同样的,x - y + n 的值也列出来
(5) (4) (3) (2) (1)
(6) (5) (4) (3) (2)
(7) (6) (5) (4) (3)
(8) (7) (6) (5) (4)
(9) (8) (7) (6) (5)
可以看出从左上到右下的对角线的值都是相等的。
来自843. n-皇后问题 - AcWing题库
其他的直接套dfs模板即可。
两种写法
n−皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
现在给定整数 n,请你输出所有的满足条件的棋子摆法。
输入格式
共一行,包含整数 n。
输出格式
每个解决方案占 n 行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。
其中
.
表示某一个位置的方格状态为空,Q
表示某一个位置的方格上摆着皇后。每个方案输出完成后,输出一个空行。
注意:行末不能有多余空格。
输出方案的顺序任意,只要不重复且没有遗漏即可。
数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q.. ...Q Q... ..Q...Q. Q... ...Q .Q..
写法一:
// 截距问题,up代表向上的斜率,down代表向下的斜率,如果斜率是负数,那么就表示为n+abs(k),列就用link表示
// dfs遍历行,因此不用对行进行标记
import java.util.*;class Main{static int N = 10;static int n;static String[][] a = new String[N][N];static boolean[] up = new boolean[2*N]; // 斜率为1的截距,截距可能为负数static boolean[] down = new boolean[2*N]; // 斜率为-1的截距,截距都为正数static boolean[] link = new boolean[N]; // 列public static void main(String[] args){Scanner in = new Scanner(System.in);n = in.nextInt();for(int i=0;i<n;i++) // 将所有的点都初始化为"."for(int j=0;j<n;j++)a[i][j] = "."; dfs(0); // 0表示行,从第0行开始}public static void dfs(int x){if(x==n) { // 遍历到最后一行,输出,返回for(int i=0;i<n;i++){for(int j=0;j<n;j++){System.out.print(a[i][j]);if(j==n-1) System.out.println();}}System.out.println();return;}for(int i=0;i<n;i++){ // 遍历第x行int up_c = x-i>0?x-i:n+i-x; // 计算(x,i)点的两个截距int down_c = x+i;if(up[up_c]==false&&down[down_c]==false&&link[i]==false){ // 如果这个点能放a[x][i] = "Q"; up[up_c]=true;down[down_c]=true;link[i]=true;dfs(x+1);// 回溯 ,(有:该位置可以放皇后,但是不放的含义)a[x][i] = "."; up[up_c]=false;down[down_c]=false;link[i]=false;}}return;}
}
写法二:
需要标记行
import java.util.*;class Main{static final int N = 10;static int n;static char[][] g = new char[N][N];static boolean[] row = new boolean[N]; // 行static boolean[] col = new boolean[N]; // 列static boolean[] dg = new boolean[2*N]; // k = -1static boolean[] udg = new boolean[2*N]; // k = 1public static void main(String[] args){Scanner in = new Scanner(System.in);n = in.nextInt();for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j] = '.';dfs(0,0,0);//从左下角(0,0)开始搜,记录Q的个数}static void dfs(int x,int y,int q){ // q用来记录皇后的数目if(y==n) { // 遍历当前行的最后一个y=0;x++;}if(x==n){ // 行遍历完if(q==n){ // 并且皇后数量等于nfor(int i=0;i<n;i++){ // 输出for(int j=0;j<n;j++){System.out.print(g[i][j]);} System.out.println(); }System.out.println(); }return;}//当前位置不放皇后dfs(x,y+1,q);//当前位置放皇后放皇后if(row[x]!=true&&col[y]!=true&&dg[x+y]!=true&&udg[n-x+y]!=true){g[x][y] = 'Q';row[x]=col[y]=dg[x+y]=udg[n-x+y]=true;dfs(x,y+1,q+1);g[x][y] = '.';row[x]=col[y]=dg[x+y]=udg[n-x+y]=false;}}
}