(图:AcWing 843. n-皇后问题(按行枚举或按每个元素枚举) - AcWing
#include <iostream>
using namespace std;
const int N = 20; //为什么不是10 因为对角线的条数为2n-1
// bool数组用来判断搜索的下一个位置是否可行
// col列,dg对角线,udg反对角线
// g[N][N]用来存路径
int n;
char g[N][N];//因为数组里的元素是"." 和 Q 两者都被定义为字符型 故存放的的数组定义为char
bool col[N], dg[N], udg[N];
void dfs(int u) { //按行枚举,且经过分析,每行只能有一个皇后
// u == n 表示已经搜了n行,故输出这条路径
if (u == n) {
for (int i = 0; i < n; i ++ ) cout << g[i] << endl; //g[i]代表二维数组的第i行 表示换行
puts(""); // 换行 空出一行
return;
}
// 枚举u这一行,搜索合法的列
int x = u;
for (int y = 0; y < n; y ++ )
// 剪枝(对于不满足要求的点,不再继续往下搜索)
if (col[y] == false && dg[y - x + n] == false && udg[y + x] == false) {
col[y] = dg[y - x + n] = udg[y + x] = true;
g[x][y] = 'Q';//不可用" "
dfs(x + 1); //迭代上下完全对称
g[x][y] = '.'; //不可用" "
col[y] = dg[y - x + n] = udg[y + x] = false; // 恢复现场
}
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
g[i][j] = '.';//不可用" "
dfs(0);
return 0;
}
复盘独立敲一遍的错误汇总:
#include <iostream>
using namespace std;
const int N = 20;//因为斜对角线的个数为2n-1
int n;
char g[N][N];//将棋盘定义为一个二维数组
bool col[N],dg[N],udg[N];//用来标记是否能用
void dfs(int u)
{
if(u==n)//如果最后一行也填完,则输出
{
for(int i=0;i<n;i++)
{
cout<<g[i]<<endl;//n*n的二维数组可视为n行含n个元素的一维数组,此处为输出第i行
}
cout<<endl;//每个结果之间有空行
}
int x=u;
for(int y=0;y<n;y++)
{
if(!col[y]&& !dg[y-x+n] &&!udg[x+y])//注意:正对角线为竖轴-横轴
//1.若对于第x行,第y列此空位,同列+正对角线+副对角线都未被利用,则可填入
//2.为什么不考虑同行呢,因为根据要求,直接安排每一行只能填一个,以此来简化操作
{
g[x][y]='Q';
col[y]=dg[y-x+n]=udg[x+y]=true;//col[y] col表示列
dfs(u+1);//递归填好,到下一行
//递归上下操作完全对称,但具体操作内容相反
col[y]=dg[y-x+n]=udg[x+y]=false;//恢复现场:1.状态 2.
g[x][y]='.';
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)//预先将所有位置填.表示空
{
for(int j=0;j<n;j++)
{
g[i][j]='.';
}
}
dfs(0);
return 0;
}
/*
此次复盘错误点
1.主函数未把棋盘空位置'.'(不是cin>>'.')
2. 对于char 变量 用'' 而非""
3.正对角线为 竖轴-横轴+n
4.对角线的条数为2n-1 故设置const 常量作为数组空间时,一定记得是否够用不溢出
5.col为列
6.main 不要写成mian啊啊啊啊
*/