• 噩梦(双向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;
    } 
  • 相关阅读:
    linux之awk命令
    HDU 2097 Sky数 进制转换
    HDU 2077 汉诺塔IV
    HDU 2094 产生冠军 dfs加map容器
    HDU 2073 叠框
    HDU 2083 简易版之最短距离
    HDU 2063 过山车 二分匹配
    天梯 1014 装箱问题
    天梯 1214 线段覆盖
    天梯 1098 均分纸牌
  • 原文地址:https://www.cnblogs.com/AK-ls/p/11447289.html
Copyright © 2020-2023  润新知