题解 | #maze#
maze
https://ac.nowcoder.com/acm/problem/15665
题目考点:bfs + 优先队列
题目概述:每张地图有起点、终点、陷阱、传送门,求最短时间。注意情况有以下几种:起点有陷阱、传送门终点有陷阱、坐传送门还不如走过去时间短等。前两种问题用数组标记即可;第三种情况用优先队列维护,保证不管是坐传送门还是不开启传送门,到达该点的时间是划算的
#include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; typedef long long ll; #define tb std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); ll n, m, t; ll a1, a2, b1, b2; char map[310][1010]; ll smap[1010][1010]; ll dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; struct poss{ ll x, y, step; ll xj, yj; }; //小根堆优先队列自定义比较器 struct cmp{ bool operator ()(const poss &x, const poss &y) { if(x.step >= y.step)return 1; return 0; } }; //使用优先队列 priority_queue<poss, vector<poss>, cmp> r; int main() { //tb; poss s, next; while(cin>>n>>m>>t){ ll flag = 0, findt = 0; memset(smap, 0, sizeof(smap)); while(!r.empty())r.pop(); //输入地图 for(ll i = 1; i <= n; i++)cin>>map[i]; //处理传送门 while(t--){ cin>>a1>>a2>>b1>>b2; a1 += 1; a2 += 1; b1 += 1; b2 += 1; if(map[a1][a2] == '#'||map[b1][b2] == '#')continue; s.x = a1; s.y = a2; s.xj = b1; s.yj = b2; s.step = 1e9; smap[a1][a2] = -1; r.push(s); } //寻找起点并进入队列 for(ll i = 1; i <= n; i++) for(ll j = 1; j <= m; j++) if(map[i][j] == 'S'){s.x = i; s.y = j; s.step = 0; r.push(s);} //bfs大法 while(!r.empty()){ if(findt) break; s = r.top(); //四个方向拓展 for(ll i = 0; i < 4; i++){ next.x = s.x + dir[i][0]; next.y = s.y + dir[i][1]; //找到就返回 if(map[next.x][next.y] == 'T'){ cout<<s.step + 1<<'\n'; flag = 1; findt = 1; break; } //有传送门且开启(就是将出口入队) if(smap[next.x][next.y] == -1){ next.x = s.xj; next.y = s.yj; next.step = s.step + 3; if(!smap[next.x][next.y] || smap[next.x][next.y] > next.step) r.push(next), smap[next.x][next.y] = next.step; } //没有传送门或者有传送门但没开启 next.step = s.step + 1; if(!smap[next.x][next.y] || smap[next.x][next.y] > next.step) if(next.x > 0 && next.x <= n && next.y > 0 && next.y <=m && map[next.x][next.y] != '#') r.push(next), smap[next.x][next.y] = next.step; } r.pop(); } if(!flag)cout<<"-1\n"; } return 0; }
题解专栏 文章被收录于专栏
希望不断进步