本题可以用和全排列一样的思想来做。
方法一:可以确定的是,一共有n行,每一行必定会放一个皇后,因此只需要枚举每一行,判断皇后放到哪个位置。
#include <iostream>
#include<cstdio>
using namespace std;
const int N = 20;//N为了对角线要开大一些
int n;
char g[N][N];
bool col[N],dg[N],udg[N];//列,对角线,反对角线的判重数组
void dfs(int u)
{
if(u == n)//如果搜到了第n行,就直接输出
{
for(int i = 0;i < n;i++)
{
cout << g[i] << endl;
}
cout << endl;
return;
}
for(int i = 0;i < n;i++)
{
if(!col[i] && !dg[u + i] && !udg[n - u + i])
{
g[u][i] = 'Q';
col[i] = dg[u + i] = udg[n - u + i] = true;
dfs(u + 1);
col[i] = dg[u + i] = udg[n - u + i] = false;
g[u][i] = '.';//恢复现场
}
}
}
int main()
{
cin >> n;
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
g[i][j] = '.';//先初始化
}
}
dfs(0);//从第0行开始搜索
return 0;
}
方法二:
可以对于每一个位置,都有放和不放这两种选择,于是从第一个位置一直遍历到最后一个位置,去搜索。
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 20;
char g[N][N];
int n;
bool row[N],col[N],dg[N],udg[N];//对行、列、正对角线,反对角线做一个判重数组
void dfs(int x,int y,int sum)//行,列,总皇后数
{
if(sum > n) return;//皇后数大于n退出
if(y == n)如果列==n,证明一行走到头了,就进入下一行,列为0,行+1
{
y = 0;
x++;
}
if(x == n)//如果行走完了,判断皇后数是否等于n
{
if(sum == n)
{
for (int i = 0; i < n; i++) {
puts(g[i]);
}
puts("");
}
return;
}
dfs(x,y + 1,sum);//对于每一个位置,都有放和不放皇后这两种选择,这种是不放皇后,于是列+1
//下面这种是放皇后的情况
if(!row[x] && !col[y] && !dg[x + y] && !udg[y - x + n])//先判重
{
g[x][y] = 'Q';
row[x] = col[y] = dg[x + y] = udg[n - x + y] = true;
dfs(x,y + 1,sum + 1);
row[x] = col[y] = dg[x + y] = udg[n - x + y] = false;
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,0,0);//从第0行第0列开始遍历,皇后数量为0
return 0;
}