zoukankan      html  css  js  c++  java
  • 噩梦(双向BFS)

    给定一张N*M的地图,地图中有1个男孩,1个女孩和2个鬼。

    字符“.”表示道路,字符“X”表示墙,字符“M”表示男孩的位置,字符“G”表示女孩的位置,字符“Z”表示鬼的位置。

    男孩每秒可以移动3个单位距离,女孩每秒可以移动1个单位距离,男孩和女孩只能朝上下左右四个方向移动。

    每个鬼占据的区域每秒可以向四周扩张2个单位距离,并且无视墙的阻挡,也就是在第k秒后所有与鬼的曼哈顿距离不超过2k的位置都会被鬼占领。

    注意: 每一秒鬼会先扩展,扩展完毕后男孩和女孩才可以移动。

    求在不进入鬼的占领区的前提下,男孩和女孩能否会合,若能会合,求出最短会合时间。

    输入格式

    第一行包含整数T,表示共有T组测试用例。

    每组测试用例第一行包含两个整数N和M,表示地图的尺寸。

    接下来N行每行M个字符,用来描绘整张地图的状况。(注意:地图中一定有且仅有1个男孩,1个女孩和2个鬼)

    输出格式

    每个测试用例输出一个整数S,表示最短会合时间。

    如果无法会合则输出-1。

    每个结果占一行。


    emmmmm, 当时就打了个测试程序就回班了, 回来之后看到我的代码里有这个东西:

     啊啊啊, 孟神, 你的算法进阶真不是我拿的啊。
    进入正题--

    求步数的话我们很容易想到BFS, 但这是两个人, 其实也很容易想到双向BFS, 创建两个队列, 在合法的状态下同时搜索, 当一个人搜索到另一个点人访问过的点时, 此时的步数就是最少步数;

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 5e5 + 100;
    const int MAXM = 3e3 + 10;
    
    template < typename T > inline void read(T &x) {
        x = 0; T ff = 1, ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') ff = -1;
            ch = getchar();
        } 
        while(isdigit(ch)) {
            x = (x << 1) + (x << 3) + (ch ^ 48);
            ch = getchar();
        } 
        x *=ff;
    } 
    
    template < typename T > inline void write(T x) {
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) write(x / 10); 
        putchar(x % 10 + '0'); 
    } 
    
    int T, n, m;
    int vis[MAXM][MAXM];
    int dx[5] = {1, 0, -1, 0};
    int dy[5] = {0, 1, 0, -1};
    char ch[MAXM][MAXM];  
    pair < int, int > boy, girl,  ghost[2];
    
    // 梁神我的算法进阶是不是在你那 -- msm 
    
    inline bool check(int xx, int yy, int dis) {
        if(xx < 0 || xx >= n || yy < 0 || yy >= m || ch[xx][yy] == 'X') return false;
        for(int i = 0; i < 2; ++i) {
            if(abs(xx - ghost[i].first) + abs(yy - ghost[i].second) <= 2 * dis) return false;
        }
        return true;
    }
    
    inline int BFS() {
        memset(vis, 0, sizeof(vis));
        queue < pair < int, int > > qb, qg;
        qb.push(boy);
        qg.push(girl);
        int dis = 0;
        while(!qb.empty() || !qg.empty()) {
            ++dis;
            for(int i = 0; i < 3; ++i) {
                int len = qb.size();
                for(int j = 0; j < len; ++j) {
                    pair < int, int > x;
                    x = qb.front();
                    qb.pop();
                    int a = x.first, b = x.second;
                    if(!check(a, b, dis)) continue;
                    for(int k = 0; k < 4; ++k) {
                        int u = a + dx[k], v = b + dy[k];
                        if(check(u, v, dis)) {
                            if(vis[u][v] == 2) return dis;
                            if(!vis[u][v]) {
                                vis[u][v] = 1;
                                qb.push({u, v});
                            }
                        }
                    }
                }
            }
            int len = qg.size(); 
            for(int i = 0; i < len; ++i) {
                pair < int, int > x; 
                x = qg.front(); 
                qg.pop(); 
                int a = x.first, b = x.second; 
                if(!check(a, b, dis)) continue; 
                for(int k = 0; k < 4; ++k) { 
                    int u = a + dx[k], v = b + dy[k]; 
                    if(check(u, v, dis)) {
                        if(vis[u][v] == 1) return dis;
                        if(!vis[u][v]) {
                            vis[u][v] = 2;
                            qg.push({u, v});
                        }
                    }
                }
            }
            
        }
        return -1;
    }
    
    int main() {
        read(T);
        while(T--) {
            read(n); read(m);
            for(int i = 0; i < n; ++i) {
                scanf("%s", ch[i]);
            }
            int tot = 0;
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < m; ++j) {
                    if(ch[i][j] == 'M') boy = {i, j};
                    else if(ch[i][j] == 'G') girl = {i, j};
                    else if(ch[i][j] == 'Z') ghost[tot++] = {i ,j};
                }
            }
            write(BFS());
            puts("");
        } 
        return 0;
    } 
  • 相关阅读:
    SQL Server逻辑读、预读和物理读
    SQL Server 视图
    SQL Server存储机制
    SQLServer
    数据库配置问题整理贴
    分析存储过程重编译的起因以及避免
    存储过程重编译的优点、缺点、确定引发语句
    查询反模式
    查询反模式
    状压DP的总结
  • 原文地址:https://www.cnblogs.com/AK-ls/p/11447289.html
Copyright © 2011-2022 走看看