先上代码!
#include<iostream>
using namespace std;
const int N = 20;
int n;
bool row[N],col[N], dg[N], udg[N];
char g[N][N];
void dfs(int x, int y, int z)
{
if (y == n) y = 0, x++; //判断y是否已经抵达边界,抵达后,x+1进行下一行
if (x == n)
{
if (z == n) //皇后放完
{
for (int i = 0; i < n; i++)puts(g[i]); //输出棋盘
cout << "\n";
}
return;
}
//放皇后
if(!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n])//x轴,y轴,斜着的两条线都没有皇后时
{
g[x][y] = 'Q'; //放一个皇后
row[x] = col[y] = dg[x + y] = udg[x - y + n] = true; //此时这些线被占住了
dfs(x+1, 0, z + 1);//继续这个流程,x+1直接换行,从y = 0开始,z+1下一个皇后
row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;//这叫回溯
g[x][y] = '.'; //这叫回溯
}
//不放皇后, z不加1;y+1来像后面退格
dfs(x, y + 1, z);
}
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);
return 0;
}
运算结果:
4
.Q..
...Q
Q...
..Q.
..Q.
Q...
...Q
.Q..
5
Q....
..Q..
....Q
.Q...
...Q.
Q....
...Q.
.Q...
....Q
..Q..
.Q...
...Q.
Q....
..Q..
....Q
.Q...
....Q
..Q..
Q....
...Q.
..Q..
Q....
...Q.
.Q...
....Q
..Q..
....Q
.Q...
...Q.
Q....
...Q.
Q....
..Q..
....Q
.Q...
...Q.
.Q...
....Q
..Q..
Q....
....Q
.Q...
...Q.
Q....
..Q..
....Q
..Q..
Q....
...Q.
.Q...
是的,代码贼短,这个用到了深搜算法,DFS;理解了其实很简单;注释在代码里面有,主要讲一下回溯和剪枝,如图:
这道题就是问1 2 3所有排序;画图就是先在第一个位置填1,再在第二位置,第三个位置以次填2,3;然后你发现没数字可以填了,就可以回去一次1 2 3 - > 1 2 _,然后发现还是只能填3,就在回去一次 1 2 _ -> 1 _ _,然后可以填3;这就是回溯,这个代码我也整出来吧,可以和八皇后一起看一下:
#include<iostream>
using namespace std;
const int N = 10;
bool st[N]; //这个数有没有用过
int n;
int path[N];
void dfs(int u)
{
if (u == n)
{
for (int i = 0; i < n; i++) cout << path[i] << " ";
cout << "\n";
return;
}
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;
}
完毕,不懂就多看看……
算了,再给你们整个图,方便你们理解,文字描述就不写了,就是不断回溯的流程:
return后Q -> .,并往后退判断成不成立,不成立就继续回溯,然后直接回溯到第一行,第一行终于成立了,然后就继续了。( !保姆级教程!)
这下真的完了