zoukankan      html  css  js  c++  java
  • 刷题笔记 -宽搜bfs和深搜dfs

    bfs

    宽搜的一般格式:
    1.定义一个判重数组st
    2.队列初始化
    3.while(queue非空)

    • 从队首取出元素
    • 扩展与取出元素相连且符合条件的元素,加入队列
      4.可以使用C++提供的队列,但是定义结构体数组模拟队列也不复杂。

    献给阿尔吉侬的花束

    代码1-使用queue:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    
    using namespace std;
    #define x first
    #define y second
    typedef pair<int ,int> PII;
    const int N = 210;
    
    int r,c;
    char maz[N][N];
    int cnt[N][N];
    bool st[N][N];
    
    
    int bfs(PII start , PII end)
    {
        queue<PII> q;
        int d[4] = {0 , 0, 1 ,-1} , f[4] = {1 , -1 , 0 , 0}; 
        memset(cnt , 0 ,sizeof cnt);
        memset(st , 0 , sizeof st);
        q.push(start);   st[start.x][start.y] = true;
        while(q.size())
        {
            PII t = q.front();
            q.pop();
           
            for(int i = 0 ; i < 4; i++)
            {
                 int x = t.x + d[i], y = t.y + f[i];
                 //边界判断
                 if(x < 0 || x >= r || y < 0 || y >= c)   continue;
                 //如果已经访问或者是墙
                 if(st[x][y] || maz[x][y] == '#')    continue;
                 
                 cnt[x][y] = cnt[t.x][t.y] + 1;
                 st[x][y] = true;
                 if(x == end.x && y == end.y)   return cnt[x][y];
                 q.push({x,y});
            }
        }
        return -1;
    }
    
    int main(void)
    {
        int t;
        cin >> t;
        PII start, end;
        
        while(t--)
        {
            cin >> r >> c;
            for(int i = 0; i < r; i++)  scanf("%s" ,maz[i]);
            
            for(int i = 0; i < r; i++)
                for(int j = 0; j < c; j++)
                    if(maz[i][j] == 'E')   start = {i , j};
                    else if(maz[i][j] == 'S') end = {i , j};
            
            int ans = bfs(start , end);
            if(ans != -1)   printf("%d
    ",ans);
            else    printf("oop!
    ");
        }
    }
    

    代码2 -模拟队列

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    #define x first
    #define y second
    typedef pair<int ,int> PII;
    const int N = 210;
    
    int r,c;
    char maz[N][N];
    int cnt[N][N];
    bool st[N][N];
    
    
    int bfs(PII start , PII end)
    {
        //如果不每一次重新定义queue,那么上一次的会残留
        PII q[r * c];
        int d[4] = {0 , 0, 1 ,-1} , f[4] = {1 , -1 , 0 , 0}; 
        memset(cnt , 0 ,sizeof cnt);
        memset(st , 0 , sizeof st);
        int hh = 0,tt = 0;
        q[hh] = start;
        st[start.x][start.y] = true;
        
        while(hh <= tt)
        {
            //pop的返回值是void ,所以需要使用front
            PII t = q[hh++];
           
            for(int i = 0 ; i < 4; i++)
            {
                 int x = t.x + d[i], y = t.y + f[i];
                 //边界检查
                 if(x < 0 || x >= r || y < 0 || y >= c)   continue;
                 //是否已经访问,是否为墙
                 if(st[x][y] || maz[x][y] == '#')    continue;
                 
                 
                 cnt[x][y] = cnt[t.x][t.y] + 1;
                 st[x][y] = true;
                 if(x == end.x && y == end.y)   return cnt[x][y];
                 q[++tt] = {x, y};
            }
        }
        return -1;
    }
    
    int main(void)
    {
        int t;
        cin >> t;
        PII start, end;
        
        while(t--)
        {
            cin >> r >> c;
            for(int i = 0; i < r; i++)  scanf("%s" ,maz[i]);
            
            for(int i = 0; i < r; i++)
                for(int j = 0; j < c; j++)
                    if(maz[i][j] == 'E')   start = {i , j};
                    else if(maz[i][j] == 'S') end = {i , j};
            
            int ans = bfs(start , end);
            if(ans != -1)   printf("%d
    ",ans);
            else    printf("oop!
    ");
        }
    }
    

    dfs

    1.一般来说,深搜能求出一个解,而宽搜会遍历所有的解。例如在求最短路径时用宽搜比较好(深搜也可以但是麻烦)
    2.宽搜不会爆栈,但深搜可能会,但是深搜的代码相对简单
    3.深搜是否进行现场恢复对应两种模型:
    - 恢复:棋盘
    - 不恢复:迷宫

    全球变暖

    代码1 -dfs

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    const int N = 1010;
    
    int d[4] = {-1 , 0 , 1 , 0} , f[4] = {0 , 1 , 0 , -1};
    char g[N][N];
    bool st[N][N];
    int n;
    int ch;
    void dfs(int x ,int y)
    {
        g[x][y] = '!';
        bool is = true;
        for(int i = 0 ; i < 4; i++)
        {
            int a = x + d[i] , b = y + f[i];
            if(a < 0 || a >= n || b < 0 || b >= n)  continue;
            if(g[a][b] == '.')      is = false;
            if(g[a][b] == '#')      dfs(a , b);
        }
        if(is)   ch = 1;
    }
    
    int main(void)
    {
        cin >> n;
        
        for(int i = 0; i < n; i++)    scanf("%s" , g[i]);
        
        bool is;
        int cnt = 0;
        for(int i = 0; i < n ; i++)
            for(int j = 0; j < n; j++)
                if(g[i][j] == '#')
                {
                        dfs(i , j);
                        if(!ch) cnt++;
                        ch = 0;
                }
        cout << cnt << endl;
        
        return 0;
    }
    

    代码2 -bfs

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define x first
    #define y second
    
    using namespace std;
    
    typedef pair<int, int> PII;
    
    const int N = 1010;
    
    int n;
    char g[N][N];
    bool st[N][N];
    PII q[N * N];
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};
    
    void bfs(int sx, int sy, int &total, int &bound)
    {
        int hh = 0, tt = 0;
        q[0] = {sx, sy};
        st[sx][sy] = true;
    
        while (hh <= tt)
        {
            PII t = q[hh ++ ];
    
            total ++ ;
            bool is_bound = false;
            for (int i = 0; i < 4; i ++ )
            {
                int x = t.x + dx[i], y = t.y + dy[i];
                if (x < 0 || x >= n || y < 0 || y >= n) continue;  // 出界
                if (st[x][y]) continue;
                if (g[x][y] == '.')
                {
                    is_bound = true;
                    continue;
                }
    
                q[ ++ tt] = {x, y};
                st[x][y] = true;
            }
    
            if (is_bound) bound ++ ;
        }
    }
    
    int main()
    {
        scanf("%d", &n);
    
        for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);
    
        int cnt = 0;
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < n; j ++ )
                if (!st[i][j] && g[i][j] == '#')
                {
                    int total = 0, bound = 0;
                    bfs(i, j, total, bound);
                    if (total == bound) cnt ++ ;
                }
    
        printf("%d
    ", cnt);
    
        return 0;
    }
    
  • 相关阅读:
    YAML 语法
    mysqladmin
    CentOS7
    MySQL 基准测试
    Sqlite 约束条件 Constraints
    sqlite3数据库 sqlite3_get_table
    MFC中使用sqlite3操作数据库
    数据库函数:sqlite3_exec() SQL语句
    VS2013 生成sqlite3动态连接库及sqlite3.dll的调用
    Windows下VS2013创建与使用动态链接库(.dll)
  • 原文地址:https://www.cnblogs.com/zy200128/p/12675972.html
Copyright © 2011-2022 走看看