HOJ 1242 Rescue

这一篇博客质量不咋地,思路有点复杂,建议去看使用优先队列的。
基本思路在注释中写了。
不行了,渣渣一个,只能写到肝疼,洗洗睡了。

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int MAXN = 200 + 5, INF = 99999999;
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };

typedef struct point {
	int x, y, t;//t记录到达(x, y)点的最短时间
}point;

char map[MAXN][MAXN];//地图
int n, m;//地图大小

int can(point p) {//判断一个点是否在地图上且不是墙
	if (p.x >= 0 && p.y >= 0 && p.x < n && p.y < m && map[p.x][p.y] != '#') return 1;
	return 0;
}

int main() {
	int flag;
	point S, c;
	vector<point> vec;//这里用了vector存储标记数组
	queue<point> Q;
	queue<point> b;
	/*借助b队列模拟实现优先队列功能
	把Q中取出来的点进行扩展
	只要是可以走的点且不为x,则时间+1;如果是x则时间需要再加1
	这时把扩展为x的点存到b中,在被扩展的点完成之后,在把b中的点加到Q的末端
	这样就实现了Q中元素时间从小到大排列
	*/
	vector<point>::iterator it;
	while (cin >> n >> m) {
		flag = 0;
		Q = queue<point>();
		b = queue<point>();
		vec.clear();
		for (int i = 0; i < n; i++)
			cin >> map[i];
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				if (map[i][j] == 'a') {
					S.x = i;
					S.y = j;
					S.t = 0;
				}
		vec.push_back(S);
		Q.push(S);
		while (!Q.empty()) {
			int loc = 0;
			point p0 = Q.front();
			Q.pop();
			for (int i = 0; i < 4; i++) {
				point p;
				p.x = p0.x + dir[i][0];
				p.y = p0.y + dir[i][1];
				p.t = p0.t + 1;//在上一个点的时间时间上+1,因为走了一步
				if (!can(p)) continue;//该点非法或不可走时,直接到下一个检索的点
				for (it = vec.begin(), loc = 0; it != vec.end(); it++, loc++) {
					if ((*it).x == p.x && (*it).y == p.y) {
						break;
					}
					if (it == vec.end() - 1) {
						c = p;
						c.t = INF;
						vec.push_back(c);
						loc++;
						break;
					}
				}
				switch (map[p.x][p.y]) {
				case 'r':
					flag = 1;
					cout << p.t << endl;
					break;
				case '.':
					if (vec[loc].t <= p0.t) break;
					Q.push(p);
					vec[loc].t = p0.t;
					break;
				case 'x':
					if (vec[loc].t <= p.t + 1) break;
					c = p;
					c.t++;//因为x代表守卫,需要多一个时间,所以在上面的这个if判断也要有一个+1的操作
					b.push(c);
					vec[loc].t = p0.t + 1;
					break;
				}//switch
				if (flag == 1)
					break;
			}//for
			if (flag == 1)
				break;
			while (!b.empty()) {
				Q.push(b.front());
				b.pop();
			}//if(!b.empty())
		}//while(!Q.empty())
		if (flag == 0)
			cout << "Poor ANGEL has to stay in the prison all his life." << endl;
	}//while(cin >> n >> m)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值