DFS
#include<iostream>
using namespace std;
const int N = 10;
int n;
int path[N];
bool st[N];
void dfs(int u) {
if (u == n) {
for (int i = 0; i < n; i++) {
cout << path[i] << ' ';
}
cout << endl;
return;
}
for (int i = 1; i <= n; i++) {
if (!st[i])
{
path[u] = i;
st[i] = true;
/*DFS 会尽量往深处搜索,当确定当前的点不能再延伸时便会回溯。
回溯要注意恢复现场,即回溯到上一个状态。*/
dfs(u + 1);
//注意:一直向深,不能延伸时再回溯
st[i] = false;
}
}
}
int main() {
cin >> n; dfs(0);
}
cols(列数)和rows(行数)
***dg (对角线) 和 udg(反对角) ***
剪枝
皇后问题
#include<iostream>
using namespace std;
const int N = 20;
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++)puts(g[i]);
puts("");
return;
}
//y=-x+b -> b=y+x dg=i+u
//x是行,y是列 坐标
for (int i = 0; i < n; i++)
//按行枚举,不需要row
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);
return 0;
}
皇后问题原始做法
// n 皇后问题的原始做法
#include<iostream>
using namespace std;
const int N = 20;
int n;
char g[N][N];
bool row[N], col[N], gd[N], ugd[N]; // 行,列,主对角线,副对角线
void dfs( int x, int y, int s ) // x 为行号,y 为列号,s 为已经定位的皇后个数
{
if( y == n ) // 已经遍历完 x 行的每列
{
x++; // 下一行
y = 0; // 重新从第 0 列开始
}
if( x == n ) // 遍历完 x 行
{
if( s == n ) // 已经全部定位完 n 个皇后
{
for( int i = 0; i < n; i++ ) puts( g[i] ); // 输出结果
puts("");
}
return;
}
// ( x, y ) 不放皇后,直接判断下一个格子,定位的皇后数 s 没有变化
dfs( x, y + 1, s );
// 若在 ( x, y ) 放皇后,则要判断该位置是否符合条件
// 若条件满足,接着向后判断,否则剪枝(即不用再向后遍历)
if( !row[x] && !col[y] && !gd[ x + y ] && !ugd[ x - y + n ] )
{
// 符合条件
g[x][y] = 'Q';
row[x] = col[y] =gd[ x + y ] = ugd[ x - y + n ] = true;
// 继续向后遍历
dfs( x, y + 1, s + 1 );
// 恢复现场
row[x] = col[y] = gd[ x + y ] = ugd[ x - y + n ] = false;
g[x][y] = '.';
}
}
int main()
{
scanf( "%d", &n );
for( int i = 0; i < n; i++ )
for( int j = 0; j < n; j++ )
g[i][j] = '.';
dfs( 0, 0, 0 );
return 0;
}