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:
Copy
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 @   Nepenthe8  阅读(140)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示