Ryanlyt / algorithm-learning

The firse
0 stars 0 forks source link

9.13 #5

Open Ryanlyt opened 1 year ago

Ryanlyt commented 1 year ago

DFS 深度优先搜索(又称暴力搜索,dfs没有一个通用的模板,最重要的是把顺序想清楚(同一题目搜索的顺序可能有很多种))

数据结构:stack(不需要真的把栈写出来) 空间O(h) 不具有最短性 (用树的形式搜索) DFS重要概念:回溯(记得恢复现场)、剪枝(提前判断,没有必要继续往下搜了,直接回溯)
(凡是求最短、最少之类的用BFS,思路比较奇怪的或者对空间要求比较高的用DFS)

全排列问题 _0aa8177b135e53aa6004b383f49c66e8_-1325107531_Screenshot_2023-09-13-15-18-02-343_com alicloud databox _bf1501397fccc3ff475ddff35386eac0_1310684031_Screenshot_2023-09-13-15-40-06-339_com alicloud databox

n-皇后问题
以全排列的搜索顺序(按行枚举)
#include <bits/stdc++.h>

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;
    }

    for(int i = 0; i< n; i++){
        if(!col[i] && !dg[u + i] && !udg[n - u + i]){    //u+i,n-u+i怎么来的?小技巧:用截距的思想来看,y-x,y+x,为了非负加一个n
            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 <bits/stdc++.h>

using namespace std;

const int N = 20;

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

void dfs(int x, int y, int s){
    if(y == n) y = 0, x++;

    if(x == n){
        if(s == n){
            for(int i = 0; i < n; i++) puts(g[i]);
            puts("");
        }
        return;
    }

    //不放皇后
    dfs(x, y + 1, s);

    //放皇后
    if(!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]){
        g[x][y] = 'Q';
        row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;
        dfs(x + 1, 0, s + 1);
        // dfs(x, y + 1, s + 1); 上下两种都可以
        row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
        g[x][y] = '.';
    }
}

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;
}

_1759f937d0c0194d4835df48dd2d8ee3_-4573697_Screenshot_2023-09-13-15-40-46-618_com alicloud databox _e8b95b5a57db7036ddfa8da62a9b3e52_1552793195_Screenshot_2023-09-13-15-55-39-441_com alicloud databox _cea41805d04aa9e46954a1f4fcf58b06_1199862218_Screenshot_2023-09-13-16-00-18-297_com alicloud databox _e36ed52f4b7e522e51e58d85a4708071_-1239961203_Screenshot_2023-09-13-15-55-47-046_com alicloud databox _ec11074bee618a7fddbb6ff5f901f319_-1730274928_Screenshot_2023-09-13-16-00-13-571_com alicloud databox _7fa90886aabe42bf1cc28b04ec5a0533_-1066172400_Screenshot_2023-09-13-16-17-32-701_com alicloud databox

Ryanlyt commented 1 year ago

BFS 广度优先搜索(有一个常用的模板)

数据结构:queue 空间O(2^h) 最短路(最短路问题是包含dp(动态规划)问题的,dp问题实际上是一种特殊的最短路问题,dp问题是没有环的最短路问题) 边权都是1是才能用BFS求最短路,否则要用专门的最短路算法

queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);

while (q.size())
{
    int t = q.front();
    q.pop();

    for (int i = h[t]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true; // 表示点j已经被遍历过
            q.push(j);
        }
    }
}

_084df950dc5fd520c60c98481d022748_826435407_Screenshot_2023-09-13-16-38-20-878_com alicloud databox _b88dde51eb1f229852d0173dad90fadc_-1830219460_Screenshot_2023-09-13-16-39-11-050_com alicloud databox _d3fdaacdaa2ccd9845b4ed80d7a74470_-62372828_Screenshot_2023-09-13-17-02-38-669_com alicloud databox _bee4bf163bab8f0ef84cc70457559f7c_-1793783028_Screenshot_2023-09-13-17-03-43-316_com alicloud databox

Ryanlyt commented 1 year ago

树和图的存储

树是一种特殊的图(无环连通图),无向图是一种特殊的有向图 所以只需要考虑有向图如何存储: 邻接矩阵(不能存储重边,用得比较少,占空间太大,适合存储稠密图) g[a][b] 存储边a->b 邻接表(用的最多,用单链表实现,和拉链法相似)

// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;

// 添加一条边a->b
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

// 初始化
idx = 0;
memset(h, -1, sizeof h);

_a5bc7492dacff5d99335203e603fb6ed_1795050181_Screenshot_2023-09-13-17-11-37-755_com alicloud databox

Ryanlyt commented 1 year ago

树和图的深度优先遍历

只需要考虑有向图是怎么遍历的

int dfs(int u)
{
    st[u] = true; // st[u] 表示点u已经被遍历过

    for (int i = h[u]; i != -1; i = ne[i])    //要先memset(h, -1, sizeof h)
    {
        int j = e[i];
        if (!st[j]) dfs(j);
    }
}

_4c0653d39b55931fcc43184708a0fe55_-1166308362_Screenshot_2023-09-13-17-27-41-189_com alicloud databox _5351500770f0a506d9e60059ac24f6da_691563227_Screenshot_2023-09-13-17-29-51-110_com alicloud databox _85a98c6e32c690990571e0d3dad385e6_-846102068_1694597202552 _20d8f5bc5070caf4bf82325e806cc350_-2053568508_Screenshot_2023-09-13-17-38-29-824_com alicloud databox _ea5554e7d8e04fe0b824f2f4d68b65e6_929392398_Screenshot_2023-09-13-17-45-53-500_com alicloud databox _a546f493ef16f320dec5953f3f40c30e_2077898327_Screenshot_2023-09-13-17-45-56-191_com alicloud databox

Ryanlyt commented 1 year ago

树和图的广度优先遍历

queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);

while (q.size())
{
    int t = q.front();
    q.pop();

    for (int i = h[t]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true; // 表示点j已经被遍历过
            q.push(j);
        }
    }
}

_4f4340dc967e0f479d4ae6a226c2957d_-1068917215_Screenshot_2023-09-13-17-46-58-916_com alicloud databox _bb366176bbcd891be63edc480652f0f9_203569669_Screenshot_2023-09-13-23-21-39-306_com alicloud databox

_80d365a1be87ea512b41a805d304d609_-574005613_Screenshot_2023-09-13-23-21-46-076_com alicloud databox

_cae0ee5a795b1eb50ead314c2dfbfa69_-9056775_Screenshot_2023-09-13-23-21-51-692_com alicloud databox

Ryanlyt commented 1 year ago

拓扑排序

_8954efbff520a801657a4e4a4078442d_-1392821803_Screenshot_2023-09-13-23-22-42-046_com alicloud databox _09a1f5bb0bb15c727e28c994cc788025_417718527_Screenshot_2023-09-13-23-22-50-160_com alicloud databox _3e53d3b7844823126be9d61392e0bec6_-1527926648_Screenshot_2023-09-13-23-25-47-948_com alicloud databox _f735a28b58f83f82ce54882b9cf55284_-241599567_Screenshot_2023-09-13-23-29-23-868_com alicloud databox _9417df9da6ec5c49e450d3f7e1eec745_-782546222_Screenshot_2023-09-13-23-36-00-116_com alicloud databox _9255dbbf0b411f5e5b3af9adb8bca49e_1509702189_Screenshot_2023-09-13-23-36-16-600_com alicloud databox