POJ 4980:拯救行动(bfs操作符重载)

“ Ctrl AC!一起 AC!”

题目:忘题戳这

资料:C++ 操作符重载        C++ 优先列队       

          优先列队中的操作符重载

          friend bool

分析:正常情况下,寻找最短路径都是用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!”

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ctrl AC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值