“ Ctrl AC!一起 AC!”
题目:忘题戳这
分析:正常情况下,寻找最短路径都是用bfs,因为它有一个重要特点:第一次到达的终点的路径即为最短路径,而一般情况下最短路径就是最短时间咯。我们这题是寻找最短时间,但是这题添加的“守卫”元素,使得最短路径与最少时间不能相匹配。所以这里我们需要用到操作符重载改变队列里元素的排列规则,使得能再次使最短路径与最少时间匹配。即,第一次到达终点即为答案。
AC代码:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct node {
int x, y, time;
friend bool operator <(const node& a, const node& b) {//操作符重载,使得耗时多的排在后面
return a.time > b.time;
}
};
int dx[] = { 0,1,-1,0 };
int dy[] = { 1,0,0,-1 };
int sx, sy, r, c;
char map[205][205];
int visit[205][205];
int bfs() {
priority_queue<node> q;//优先队列
node first;
first.x = sx; first.y = sy; first.time = 0;
q.push(first);
while (!q.empty()) {
node temp = q.top(); q.pop();//这里用top()取首节点
for (int i = 0; i < 4; i++) {
int nowr = temp.x + dx[i];
int nowc = temp.y + dy[i];
int nowtime = temp.time;
if (map[nowr][nowc] == 'a') return nowtime + 1;//第一次即为答案,立即返回
//三种剪枝
if (nowr < 0 || nowr >= r || nowc < 0 || nowc >= c) continue;
if (visit[nowr][nowc]) continue;
if (map[nowr][nowc] == '#') continue;
if (map[nowr][nowc] == '@') nowtime += 1;
if (map[nowr][nowc] == 'x') nowtime += 2;
node next;
next.x = nowr; next.y = nowc; next.time = nowtime;
q.push(next);
visit[nowr][nowc] = 1;
}
}
return -1;//队列空了也没答案
}
int main() {
int t; cin >> t;
while (t--) {
cin >> r >> c;
memset(visit, 0, sizeof(visit));
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> map[i][j];
if (map[i][j] == 'r') sx = i, sy = j;
}
}
int ans=bfs();
if (ans == -1) cout << "Impossible" << endl;
else cout << ans << endl;
}
return 0;
}
感谢阅读!!!
“ Ctrl AC!一起 AC!”