• AtCoder Beginner Contest 241 F Skate(bfs、STL)


    F - Skate

    题目大意:

    每次移动,沿着一个方向一直运动,直到遇到障碍物才停下,问从起点到终点的移动次数。

    思路:

    由于之前玩过类似的游戏,题意比较好理解。

    考虑每个位置上我们有哪些选择,按照题意,我们只有上下左右四个方向,并且沿着这个方向需要碰到障碍物,否则就会出界,注意碰到障碍物就会停止,并不会立即穿过这个障碍物,这样看的话,还是相当于四个方向 bfs 寻找最短路。

    由于地图的长宽都为 1e9 我们考虑使用 map 离散化的存下障碍物。需要寻找的更新路径就在同一行或同一列,所以我们用 map<ll, set<ll>> r, c; 存下每一行(列)障碍物对应的列(行),这样在更新时就可以二分的来找出下一步的位置。

    在实现上,我是把所有点移到了 0-index 上再操作,队列使用 array<int, 2> 存当前点和步数。

    Code:
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        ll h, w, n;
        cin >> h >> w >> n;
        pair<ll, ll> st, en;
        cin >> st.first >> st.second >> en.first >> en.second;
        st.first--, st.second--, en.first--, en.second--; // 转成 0-index
        vector<pair<ll, ll>> shit(n);
        for (auto &[x, y] : shit) {
            cin >> x >> y;
            x--, y--;
        }
    
        map<ll, set<ll>> r, c;
        map<ll, ll> dis;
        for (auto [x, y] : shit) {
            r[x].insert(y);
            c[y].insert(x);
        }
    
        ll ans = -1;
    
        queue<array<ll, 2>> q;
        q.push({st.first * w + st.second, 0}); // 当前点,步数
        while (!q.empty()) {
            auto [now, d] = q.front();
            q.pop();
            if (dis.count(now) > 0) {
                continue;
            }
            dis[now] = d;
            if (now == en.first * w + en.second) {
                ans = dis[now];
                break;
            }
            ll nx = now / w, ny = now % w;
            // 同一行
            if (r.count(nx)) {
                auto p = r[nx].lower_bound(ny);
                if (p == r[nx].end()) {
                    q.push({nx * w + *prev(p) + 1, d + 1}); // 应该push shit旁边的空白点
                } else if (p == r[nx].begin()) {
                    q.push({nx * w + *p - 1, d + 1});
                } else {
                    q.push({nx * w + *prev(p) + 1, d + 1});
                    q.push({nx * w + *p - 1, d + 1});
                }
            }
            // 同一列
            if (c.count(ny)) {
                auto p = c[ny].lower_bound(nx);
                if (p == c[ny].end()) {
                    q.push({(*prev(p) + 1) * w + ny, d + 1});
                } else if (p == c[ny].begin()) {
                    q.push({(*p - 1) * w + ny, d + 1});
                } else {
                    q.push({(*prev(p) + 1) * w + ny, d + 1});
                    q.push({(*p - 1) * w + ny, d + 1});
                }
            }
        }
    
        cout << ans << "\n";
        return 0;
    }
    
  • 相关阅读:
    Flash 教程
    版面在简洁模式下去今日贴.主题贴.发贴总数的方法 Dvbbs
    Get Certificate of website by Firefox
    OpenSSL 命令说明
    Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
    Python 字符串操作(截取/替换/查找/分割)
    男子英文名释义
    AD 端口相关
    How do I obtain a Digital Certificate from my Certificate Authority (CA)?
    C,C++,java,python对比
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/15950038.html
Copyright © 2020-2023  润新知