一、n皇后问题843. n-皇后问题 - AcWing题库
题解1:
暴力枚举来搜索,每一行只能有一个皇后,就先按行再按列来枚举,列举每一种情况,即n*n种情况,怎样筛选结果呢,
这道题限制条件有三个,对于对角线,由数学知识(可以自己画个图像)知正对角线横纵坐标相减为定值,即x-y,考虑到数组下标不能为负数,所以x-y+n;反对角线横纵坐标相加为定值,即x+y。来确定对角线 ,只要有xy满足上面任意一个,就标记定值,这样就能筛选满足条件的皇后了。
见下面代码(代码我是参考别人的,不是原创哈,自己写一遍理解一下)
#include<iostream>
using namespace std;
const int N=10;
int n;
char queen[N][N];
bool row[N],col[N],dia[2*N],udia[2*N];
void dfs(int x,int y,int s)
{
if(y==n) y=0,x=x+1;
if(x==n) //行等于n
{
if(s==n) //继续判断,只有在皇后个数等于n时才是正确结果
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%c",queen[i][j]);
printf("\n");
}
printf("\n");
}
return;
}
if(!row[x]&&!col[y]&&!dia[x-y+n]&&!udia[x+y]) //该位置满足,就进入
{
queen[x][y]='Q';
row[x]=true,col[y]=true,dia[x-y+n]=true,udia[x+y]=true;
dfs(x,y+1,s+1); //表示这一行已经找到了,不能再用了,从下一列开始,保证了从左到右、从上到下的顺序
row[x]=false,col[y]=false,dia[x-y+n]=false,udia[x+y]=false;
queen[x][y]='.'; //注意这里别漏了,回溯后恢复现场
}
dfs(x,y+1,s); //上面if里的位置不满足,往下一列查看(从上到下,从左往右,以防漏掉)
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
queen[i][j]='.';
dfs(0,0,0);
return 0;
}
题解2:以行枚举搜(类比数的全排列),当处理完了当前行的所有可能性,但没有找到合适的位置放置皇后,时会执行下一行的递归调用;当所有位置都尝试完毕且无法找到合适的位置时,所有循环都结束,函数执行到最后一行`return`语句之后,会返回到上一次递归调用的地方,不断回溯,直到搜完所有可能找到最终结果。
见代码
#include<iostream>
using namespace std;
const int N=10;
int n;
char queen[N][N];
bool dia[2*N],udia[2*N],col[N];
void dfs(int s) //当前处理的行数
{
if(s==n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout<<queen[i][j];
cout<<endl;
}
cout<<endl;
return;
}
for(int i=0;i<n;i++) //一行一行的搜
{
if(!col[i]&&!dia[s+i]&&!udia[n-s+i])
{
9queen[s][i]='Q';
col[i]=dia[s+i]=udia[i-s+n]=true;
dfs(s+1);
col[i]=dia[s+i]=udia[i-s+n]=false;
queen[s][i]='.';
}
}
return;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
queen[i][j]='.';
dfs(0);
return 0;
}
直接暴搜,见代码
#include<iostream>
using namespace std;
const int N=10;
int n;
int path[N];
bool st[N];
void dfs(int u) //u表示第几个数字,即层数
{
if(u==n){
for(int i=0;i<n;i++)
printf("%d",path[i]);
printf("\n");
return; //回溯,回到递归的上一步dfs(2)、dfs(1)、dfs(0),依次,每回溯一次就往下循环一下,不放过每一条路
}
for(int i=1;i<=n;i++)
{
if(!st[i]) { //选择路径
path[u]=i;
st[i]=true;
dfs(u+1);//结束后就是回溯状态
st[i]=false; //递归函数结束后一定要记得恢复
}
}
}
int main()
{
cin>>n;
dfs(0);
return 0;
}