首页 > 其他分享 >倍增+bfs 清楚姐姐逛街

倍增+bfs 清楚姐姐逛街

时间:2023-01-31 17:12:34浏览次数:58  
标签:std nx 逛街 nxt int bfs ny 倍增 dis

题目

题意

  • 地图大小N*M,障碍物为“#”,地图上其他所有点有一个字母(“LRUD”之一,表示走的方向;“.”表示A停止)
  • 有两个人A和B,A从(\(x_t\),\(y_t\))按照地图上的标记走,B从(\(x_s\),\(y_s\))走,A走一步,B走一步(B可以上下左右随意走或者停下)
  • 给 q 个询问,每次询问是一对坐标(\(x_t\),\(y_t\)),问从A这个点出发按照地图上标记的方向走,B最快多久遇上A
  • 起点为(\(x_s\),\(y_s\))

思路

  • 朴素的方法是\(O(N * M * q)\)
    1. 从(\(x_s\),\(y_s\))bfs,为每个位置标记上一个最短到达时间ti[i][j]
    2. 从(\(x_t\),\(y_t\))再次搜索,当遇到step >= ti[i][j]时,就是答案
  • 朴素的方法显然不够过hard的,我们可以观察这个地图,发现从一个点走的空间变化和时间是正相关的(应该是这么说)
  • 所以我们可以考虑用倍增记录
    1.\(next[i * m+j][p]\)表示从\((i,j)\)出发,走\(2^p\)步的位置
    2.先根据地图,做出\(next[i * m+j][0]\)的位置
    3.然后就是经典的倍增转移啦
  • 最后是经典的从最大的倍数逐倍缩小,直到不能缩小为止,这个最小的倍数就是答案

代码

#include <bits/stdc++.h>

using i64 = long long;

constexpr int dx[] = {0, 0, -1, 1};
constexpr int dy[] = {-1, 1, 0, 0};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n, m, xs, ys, q;
    std::cin >> n >> m >> xs >> ys >> q;
    
    std::vector<std::string> s(n);
    for (int i = 0; i < n; i++) {
        std::cin >> s[i];
    }
    
    std::vector dis(n * m, -1);
    
    std::queue<std::pair<int, int>> que;
    que.emplace(xs, ys);
    dis[xs * m + ys] = 0;
    
    while (!que.empty()) {
        auto [x, y] = que.front();
        que.pop();
        
        for (int k = 0; k < 4; k++) {
            int nx = x + dx[k];
            int ny = y + dy[k];
            if (s[nx][ny] != '#' && dis[nx * m + ny] == -1) {
                dis[nx * m + ny] = dis[x * m + y] + 1;
                que.emplace(nx, ny);
            }
        }
    }
    
    const int l = 20;
    
    std::vector nxt(l, std::vector(n * m, -1));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (s[i][j] != '#') {
                int nx, ny;
                if (s[i][j] == '.') {
                    nx = i, ny = j;
                } else {
                    int k = std::string("LRUD").find(s[i][j]);
                    nx = i + dx[k];
                    ny = j + dy[k];
                    if (s[nx][ny] == '#') {
                        nx = i, ny = j;
                    }
                }
                nxt[0][i * m + j] = nx * m + ny;
            }
        }
    }
    
    for (int t = 1; t < l; t++) {
        for (int i = 0; i < n * m; i++) {
            if (nxt[t - 1][i] != -1) {
                nxt[t][i] = nxt[t - 1][nxt[t - 1][i]];
            }
        }
    }
    
    while (q--) {
        int x, y;
        std::cin >> x >> y;
        
        int u = x * m + y;
        if (dis[u] == -1) {
            std::cout << -1 << "\n";
        } else {
            int ans = 0;
            for (int t = 19; t >= 0; t--) {
                int v = nxt[t][u];
                if (dis[v] > ans + (1 << t)) {
                    ans += (1 << t);
                    u = v;
                }
            }
            ans++;
            std::cout << ans << "\n";
        }
    }
    
    return 0;
}
/*jiangly的代码*/
/*妙啊妙啊*/

标签:std,nx,逛街,nxt,int,bfs,ny,倍增,dis
From: https://www.cnblogs.com/cfddfc/p/17079842.html

相关文章

  • Knight Moves POJ-1915 <bfs>
    KnightMovesTimeLimit: 1000MS MemoryLimit: 30000KTotalSubmissions: 37011 Accepted: 17105DescriptionBackgroundMrSomurolov,fabulous......
  • 图文:深度优先遍历(DFS)和广度优先遍历(BFS)
    /***注意:left/right值若没有显示设置为null,值即为undefined*在调用二叉树前、中、后序遍历方法时,由于参数设置了默认值(tree)*所以进入了死循环*/consttree={......
  • bfs走迷宫
    广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历算法这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都......
  • 倍增LCA板子
    #include<iostream>#include<cstring>#include<algorithm>#include<vector>usingnamespacestd;constintN=5e5+10;intn,m,s,a,b;vector<int>e[N];intde......
  • 树上倍增
    https://codeforces.com/contest/702/problem/E题意:给一个n个点,n条有向边,n个权值的图,每个点一条出边问所有的点按着有向边走k的权值和,还有k条边上的最小权值是多少,......
  • 【题解】P4768 [NOI2018] 归程(树上倍增,Kruskal 重构树,dijkstra)
    【题解】P4768[NOI2018]归程作为一道NOI的D1T1,放在现在或许难度不够(?),但可能在Kruskal重构树还未普及的当时,还是相对来说比较难的一道题吧。写篇题解记录一下。题......
  • 【BFS】LeetCode 417. 太平洋大西洋水流问题
    题目链接417.太平洋大西洋水流问题思路问题可以转换成从四个边界出发,能和内部哪些点连通。因为涉及到两个可达性问题,所以用两个boolean类型矩阵分别记录一个点到太......
  • 【BFS】LeetCode 542. 01 矩阵
    题目链接542.01矩阵思路题目让求1到0的距离,其实可以转换成求0到1的距离,将所有的0作为源结点放入队列进行BFS。BFS本质上就是从源点开始的搜索算法,本题只不过是所有的......
  • 【BFS】LeetCode 1091. 二进制矩阵中的最短路径
    题目链接1091.二进制矩阵中的最短路径思路BFS找最短路模板题代码classSolution{publicintshortestPathBinaryMatrix(int[][]grid){if(grid[0][......
  • 倍增
    概述略。真让我一周把这些车出来不如~了我。真想整的话就...例题P4155[SCOI2015]国旗计划题意略。我一开始把题审错了以为是链...另外这里是要接力的,即覆盖......