用dfs,求出全排列。
//下标从1开始的代码
#include<iostream>
using namespace std;
const int N=10;
int path[N];//路径记录
bool st[N];//判断数字是否已用过 用过为true 没用过false
int n;
void dfs(int u)
{
if(u==n+1)//n位全搜完了 搜索完成
{
for(int i=1;i<=n;i++) printf("%d ",path[i]);//0~n记录每一个数
printf("\n");
return;
}
for(int i=1;i<=n;i++)//遍历看看哪些用过哪些没有用过
{
if(!st[i])//没有用过
{
path[u]=i;//赋值
st[i]=true;//标记已用过
dfs(u+1);//dfs下面一位
st[i]=false;//恢复现场,标记未用过
}
}
}
int main()
{
cin>>n;
dfs(1);//从第一位开始向下搜索
return 0;
}
解法一:
dfs按行搜索,把他看成排列问题,就是第一行,第二行……
//下标从1开始
#include<iostream>
using namespace std;
const int N=20;
char q[N][N];//q[][]用来记录皇后数组 下标从1开始
int n;
bool col[N],dg[N],udg[N];
//col[]列 dg[]副对角线(右上到左下) udg[]主对角线
void dfs(int x)
{
if(x==n+1)//如果已经检测到n+1行,说明已经结束
{
//输出皇后数组中每一个元素,不可以puts,因为是从下标1开始
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%c",q[i][j]);
printf("\n");
}
printf("\n");
return;
}
for(int y=1;y<=n;y++)//x行y列
{
if(!col[y] && !dg[x+y] && !udg[y-x+n])//第y列和两条对角线都没有用过
{
q[x][y]='Q';//赋值为 'Q'
col[y]=dg[x+y]=udg[y-x+n]=true;//true为用过
dfs(x+1);//搜索下一个
col[y]=dg[x+y]=udg[y-x+n]=false;//恢复现场
q[x][y]='.';//恢复现场
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
q[i][j]='.';//全部初始化为.
dfs(1);//从第一行开始dfs
return 0;
}
//下标从0开始 AcWing代码
#include<iostream>
using namespace std;
const int N=20;
char q[N][N];
int n;
bool col[N],dg[N],udg[N];
void dfs(int x)
{
if(x==n)
{
for(int i=0;i<n;i++) puts(q[i]);
puts("");
return;
}
for(int y=0;y<n;y++)
{
if(!col[y] && !dg[x+y] && !udg[y-x+n])
{
q[x][y]='Q';
col[y]=dg[x+y]=udg[y-x+n]=true;
dfs(x+1);
q[x][y]='.';
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++)
q[i][j]='.';
dfs(0);
return 0;
}
通过截距b来确定一条直线,x,y只要再同一条直线上,都会与b建立等式。
解法二:
按每一个点去判断能不能放
//下标从1开始
#include<iostream>
using namespace std;
const int N=20;
char q[N][N];//q[][]用来记录皇后数组 下标从1开始
int n;
bool row[N],col[N],dg[N],udg[N];
//row[]行 col[]列 dg[],udg[]两条对角线
void dfs(int x,int y,int s)//x横坐标 y纵坐标 s皇后个数
{
if(y==n+1) y=1,x++;//一行中每一列都遍历过了 到下一行第一列
if(x==n+1)//行都遍历完
{
if(s==n)//皇后个数等于n
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%c",q[i][j]);
printf("\n");
}
printf("\n");
}
return;
}
dfs(x,y+1,s);//不放皇后 直接遍历下一个格子
if(!row[x] && !col[y] && !dg[x+y] && !udg[y-x+n])//可以放
{
q[x][y]='Q';
row[x]=col[y]=dg[x+y]=udg[y-x+n]=true;
dfs(x,y+1,s+1);//遍历下一个格子,皇后个数+1
q[x][y]='.';//恢复现场
row[x]=col[y]=dg[x+y]=udg[y-x+n]=false;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
q[i][j]='.';//全部初始化为.
dfs(1,1,0);//从左上第一个点开始dfs,皇后个数为0
return 0;
}
//下标0开始
#include<iostream>
using namespace std;
const int N=20;
char q[N][N];
int n;
bool row[N],col[N],dg[N],udg[N];
void dfs(int x,int y,int s)
{
if(y==n) y=0,x++;
if(x==n)
{
if(s==n)
{
for(int i=0;i<n;i++) puts(q[i]);
puts("");
}
return;
}
dfs(x,y+1,s);
if(!row[x] && !col[y] && !dg[x+y] && !udg[y-x+n])
{
q[x][y]='Q';
row[x]=col[y]=dg[x+y]=udg[y-x+n]=true;
dfs(x,y+1,s+1);
q[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++)
q[i][j]='.';
dfs(0,0,0);
return 0;
}