[DFS模板题] 全排列以及n-皇后问题
目录
排列数字
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
利用一维数组标记
#include <iostream>
using namespace std;
const int N = 10;
int n,path[N];
bool b[N];
void dfs(int m)
{
if(m == n){
for (int i = 0; i < n; i ++ ) cout << path[i] << ' ';
cout << endl;
return ;
}
for (int i = 1; i <= n; i ++ ){
if(!b[i]){
path[m] = i;
b[i] = true;
dfs(m+1);
b[i] = false;
}
}
}
int main()
{
cin >> n;
dfs(0);
return 0;
}
利用二进制标记
#include <iostream>
using namespace std;
const int N = 10;
int n,path[N];
bool b[N];
void dfs(int m, int state)
{
if(m == n){
for (int i = 0; i < n; i ++ ) cout << path[i] << ' ';
cout << endl;
return ;
}
for (int i = 0; i < n; i ++ ){
if (!(state >> i & 1))
{
path[m] = i + 1;
dfs(m + 1, state + (1 << i));
}
}
}
int main()
{
cin >> n;
dfs(0, 0);
return 0;
}
n-皇后问题
843. n-皇后问题 - AcWing题库高质量的算法题库https://www.acwing.com/problem/content/845/
#include <iostream>
using namespace std;
const int N = 20;
int n;
char path[N][N];
bool col[N],dg[N],udg[N];//分别表示同一列,同一正对角线,同一反对角线的占用情况
void dfs(int m)
{
if(m == n){
for (int i = 0; i < n; i ++ ) puts(path[i]);
cout << endl;
return ;
}
for (int i = 0; i < n; i ++ ){
if(!col[i] && !dg[m+i] && !udg[i-m+n]){//★
path[m][i] = 'Q';
col[i] = dg[m+i] = udg[i-m+n] = true;
dfs(m+1);
col[i] = dg[m+i] = udg[i-m+n] = false;
path[m][i] = '.';
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
path[i][j] = '.';
dfs(0);
return 0;
}
对于关键操作的理解
这里妙就妙在对于状态的判定上
!col[i] && !dg[m+i] && !udg[i-m+n]
col 数组是表示该列是否被占用,比较好理解
dg 数组表示该位置(横坐标为m,纵坐标为i)所在的正向对角线(即右上到左下)是否被占用,我们可以从中看出规律,同一正对角线的横纵坐标加和相等
而udg 数组表示该位置所在的反对角线(即左上到右下)是否被占用,从中看出规律,同一反对角线的横纵坐标差值相等,而我们定义的udg 数组下标是从0开始的,为了使之合理,我们给他加个足以满足"差值+x>=0"的x, 通俗来说就是使物以类聚,并且聚得方便操作,所以上面的i-m+n也可以写作m-i+n或者m-i+15, i-m+16之类的
本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/15799081.html