AtCoder Beginner Contest 241 补题(E)
F - Skate
题意:
在\(h×w\)的地图中,有一个起点和终点,现在有\(n\)个障碍物,你现在可以选择上下左右其中一个方向进行移动,一旦选择一个方向就会一直朝着这个方向移动,遇到障碍物就会停止,进行下一步移动,否则就会掉出地图外,问到终点的最小移动次数是多少?
思路:
关键:\(stl+BFS\)
由于地图很大,但是障碍物的数量不多,所以以障碍物为关键,进行\(BFS\),每次从当前点,找到与当前同行同列的可达的障碍物,然后判断移动过去是否符合条件,点的存储用到了\(map,set\)等\(stl\)
View Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
typedef pair<int, int> PII;
map<PII, int> dis;
map<int, set<int> > r;
map<int, set<int> > c;
int h, w, n;
int sx, sy, ex, ey;
queue<PII> q;
void move(int x, int y, int step) {
if (x < 1 || x > h || y < 1 || y > w) return;
if (dis.count({x, y})) return;
q.push({x, y});
dis[{x, y}] = step;
}
signed main() {
cin >> h >> w >> n;
cin >> sx >> sy >> ex >> ey;
for (int i = 1, x, y; i <= n; i++) {
cin >> x >> y;
r[x].insert(y);
c[y].insert(x);
}
dis[{sx, sy}] = 0;
q.push({sx, sy});
while (!q.empty()) {
auto t = q.front();
q.pop();
if (t.x == ex && t.y == ey) {
cout << dis[{ex, ey}] << endl;
return 0;
}
if (r.count(t.x)) {
auto now = r[t.x].lower_bound(t.y);
if (now != r[t.x].end()) {
move(t.x, *now - 1, dis[{t.x, t.y}] + 1);
}
if (now != r[t.x].begin()) {
now--;
move(t.x, *now + 1, dis[{t.x, t.y}] + 1);
}
}
if (c.count(t.y)) {
auto now = c[t.y].lower_bound(t.x);
if (now != c[t.y].end()) {
move(*now - 1, t.y, dis[{t.x, t.y}] + 1);
}
if (now != c[t.y].begin()) {
now--;
move(*now + 1, t.y, dis[{t.x, t.y}] + 1);
}
}
}
puts("-1");
return 0;
}
G 似乎是最大流,还没学,学完找时间再补

浙公网安备 33010602011771号