[DFS模板题] 全排列以及n-皇后问题

目录

排列数字

利用一维数组标记

利用二进制标记

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之类的

posted @ 2021-10-05 19:43  泥烟  阅读(27)  评论(0编辑  收藏  举报