算法学习笔记(21)——深度优先搜索DFS

深度优先搜索DFS

深度优先搜索的思想简单来说就是“一条道走到黑”,也被称为“暴力搜索”,常用于解决需要给出所有方案的问题,因为它的搜索顺序就是能够得到一个完整的搜索路径(方案)后回溯再去搜索其它的方案。

排列数字

题目链接:AcWing 842. 排列数字

#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] << ' ';
        puts("");
        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;
}

n-皇后问题

这道题限制了任意两个皇后都不能处于同一行、同一列或同一斜线上,所以我们开行row、列col、正对角线dg、反对角线udg这四个数组用于判断当前位置能否放皇后。有两种搜索方式:

按位搜索

#include <iostream>

using namespace std;

const int N = 10, M = N * 2;

int n;
char g[N][N];   // 用于存储地图
bool row[N], col[N], dg[M], udg[M];

// 深搜函数,(x,y)表示坐标,s代表当前放置的皇后个数
void dfs(int x, int y, int s)
{
    // 已经放了n个皇后,则返回
    if (s > n) return;
    
    // 如果已经扫描到当前行的最后一个位置,则从下一行的开头开始
    if (y == n) y = 0, x ++;
    
    // 如果扫描到最后一行
    if (x == n) {
        // 判断是否放够了n个皇后
        if (s == n) {
            for (int i = 0; i < n; i ++ ) puts(g[i]);
            puts("");
        }
        return;
    }
    
    g[x][y] = '.';  // 默认当前位置没有皇后,也可以在main中对地图初始化
    
    // 要么放皇后
    if (!row[x] && !col[y] && !dg[x + y] && !udg[n - x + y]) {
        g[x][y] = 'Q';
        row[x] = col[y] = dg[x + y] = udg[n - x + y] = true;
        dfs(x, y + 1, s + 1);   // 搜索下一个位置,皇后数加一
        row[x] = col[y] = dg[x + y] = udg[n - x + y] = false;   // 恢复现场
        g[x][y] = '.';
    }
    
    // 要么不放皇后
    dfs(x, y + 1, s);
}

int main()
{
    cin >> n;
    dfs(0, 0, 0);
    return 0;
}

按行搜索

由于每一行最多只能放一个皇后,所以我们可以按行来搜索,每次枚举一行时就放一个皇后,放到第n行时一定有n个皇后。

#include <iostream>

using namespace std;

const int N = 10, M = N * 2;

int n;
char g[N][N];
bool col[N], dg[M], udg[M];

void dfs(int u)
{
    // 如果枚举到第n行,则一定放了n个皇后,输出结果
    if (u == n) {
        for (int i = 0; i < n; i ++ ) puts(g[i]);
        puts("");
        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);
    
    return 0;
}
posted @ 2022-12-09 22:07  S!no  阅读(19)  评论(0编辑  收藏  举报