title: N皇后
tags: 深度优先搜索
abbrlink: 59444
date: 2022-03-14 19:11:01
N皇后
题目来源
力扣-51N 皇后
AcWing 843. n-皇后问题
重点信息
- 皇后的个数、行数、列数总数相同,斜线总数为2n-1
- 所有皇后不能在同一行同一列同一斜线
- 要遍历出所有的可行摆放情况
笔者解析
- 可以设置三个一维boolean数组,分别用来封锁竖行,与两斜行。而横排则在传输中变换
- 使用DFS(深度优先搜索),回溯遍历
笔者代码
力扣版本
class Solution {
char[][] ch;
List<List<String>> lists = new ArrayList<>();
//三个bool函数分别表示列,正斜线和反斜线(共有2n-1条斜线)
boolean[] col = new boolean[11];
boolean[] d = new boolean[30];
boolean[] rd = new boolean[30];
public List<List<String>> solveNQueens(int n) {
//初始化队列
ch = new char[n ][n ];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
ch[i][j] = '.';
}
}
//深度优先搜索
DFS(0,n);
return lists;
}
public void DFS(int m,int n){
//当搜索数字等于n时,则搜索完毕可以存入
if (m==n){
//将数据存入队列中
List<String> list = new ArrayList<>();
for (int i = 0; i < n ; i++) {
String s = "";
for (int j = 0; j < n; j++) {
s+=ch[i][j];
}
list.add(s);
}
lists.add(list);
return;
}
//遍历每行,m可以表示当前所在行数,i可以表示当前所在列数
for (int i = 0; i < n ; i++) {
//斜线的x与y的和与差总是固定的
//则利用x+y判断正斜线是否被用,y-x判断反斜线是否被用加上N是防止溢出
if(col[i] == false && d[i+m] == false && rd[n+i-m] == false){
//将此点变成皇后Q
ch[m][i] = 'Q';
//将此点的竖线,两斜线封锁
col[i]=d[i+m]=rd[n+i-m]=true;
//继续向下一排遍历
DFS(m+1,n);
//遍历回溯后,回到曾经状态
col[i]=d[i+m]=rd[n+i-m]=false;
ch[m][i] = '.';
}
}
}
}
acwing版本
//acwing版本
import java.io.*;
/**DFS求解n皇后的求解方法*/
public class Main {
static int N = 20;
static BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
//分别记录列,对角线与反对角线
static boolean[] col = new boolean[N];
static boolean[] dl = new boolean[N];
static boolean[] rdl = new boolean[N];
static char[][] arr = new char[N][N];
static int n;
public static void main(String[] args) throws Exception{
n = Integer.valueOf(read.readLine());
String temp ;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = '.';
}
}
DFS(0);
System.out.println();
}
public static void DFS (int m){
//当n皇后排满,m是个数也是行数
if(m==n){
for (int i = 0; i < n; i++) {
System.out.println(arr[i]);
}
System.out.println();
}
for (int i = 0; i < n; i++) {
//若果m列,对角线,反对角线未被使用
//判断x+y是否被用,y-x是否被用加上N是防止溢出
// 因为两者相加与相减的大小是固定的
if(!col[i] && !dl[i+m] && !rdl[n+i-m]){
//若未被占用则记录使用
col[i] = dl[i+m] = rdl[i-m+n-1] = true;
//将此点标记为Q
arr[m][i] = 'Q';
DFS(m+1);
//回到曾经状态
col[i] = dl[i+m] = rdl[i-m+n-1] = false;
arr[m][i] = '.';
}
}
}
}