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;
}
posted @ 2022-03-01 14:31  Nepenthe8  阅读(123)  评论(0编辑  收藏  举报