AcWing 843. n-皇后问题(详细注释)
原题链接
中等
作者:
现代修士o_O
,
2021-04-27 19:20:47
,
所有人可见
,
阅读 332
//时间复杂度:按行遍历O(n*n*n!),按位置遍历O(2^(n^2))
#include <iostream>
using namespace std;
//行数列数最大值
const int N = 10;
//存储行数和列数
int n;
//二维字符数组存储图
char g[N][N];
//row[] 用来表示这一行上的数有没有被用过
//col[] 用来表示这一列上的数有没有被用过
//用截距唯一代表一条对角线
//dg[] 用来表示这一条对角线的数有没有被用过,对角线的个数等于2 * n - 1, y = x + b, b = y - x 列减去行(算法中y代表列,x是行)
//udf[] 用来表示这一条反对角线的数有没有被用过, y = - x + b, b = x + y 列加上行
bool row[N], col[N], dg[2 * N], udg[2 * N];
// void dfs(int u)//遍历第u行
// {
// if (u == n)
// {
// for (int i = 0; i < n; i ++ ) puts(g[i]);
// puts("");
// return;//递归结束
// }
//这里为什么不像按位置遍历那样,分两种情况呢?
//个人理解:按位置遍历那是未知的,每个位置有可能没有,有可能有。
//而按行来遍历,是肯定了,每行必有一个皇后,实际上每列也必有一个皇后,按列遍历和按行遍历差不多
//这么想来,如果按对角线来遍历,也要分两种情况,有和没有!
// for (int i = 0; i < n; i ++ ) //遍历列
// {
// //col判断列重复元素,dg判断正对角线重复元素,udg判断反对角线重复元素
// if (!col[i] && !dg[u - i + n] && !udg[i + u])
// {
// g[u][i] = 'Q';
// col[i] = dg[u - i + n] = udg[i + u] = true;
// //遍历下一行
// dfs(u + 1);
// //恢复现场
// g[u][i] = '.';
// col[i] = dg[u - i + n] = udg[i + u] = false;
// }
// }
// }
void dfs(int x, int y, int s)//按位置遍历,s代表皇后个数
{
if (y == n) y = 0, x++;
if (x == n)//遍历了所有的位置
{
if (s == n)//有n个皇后就输出
{
for (int i = 0; i < n; i ++ ) puts(g[i]);
puts("");
}
return ;//这个放外面!
}
//这个位置不放皇后
dfs(x, y + 1, s);
//这个位置放皇后
if (!row[x] && !col[y] && !dg[x + y] && !udg[y - x + n])
{
g[x][y] = 'Q';
row[x] = col[y] = dg[x + y] = udg[y - x + n] = true;
dfs(x, y + 1, s + 1);
//恢复现场
g[x][y] = '.';
row[x] = col[y] = dg[x + y] = udg[y - x + n] = false;
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
g[i][j] = '.'; //初始化,n行n列都为.
// dfs(0); //按行进行遍历,从第0行开始
dfs(0, 0, 0);
return 0;
}