首页 > 代码库 > ZOJ 1649 && HDU 1242 Rescue
ZOJ 1649 && HDU 1242 Rescue
Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.
Angel‘s friends want to save Angel. Their task is: approach Angel. We assume that "approach Angel" is to get to the position where Angel stays. When there‘s a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards.
You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
Input
First line contains two integers stand for N and M.
Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel‘s friend.
Process to the end of the file.
Output
For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing "Poor ANGEL has to stay in the prison all his life."
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
Author: CHEN, Xue
Source: ZOJ Monthly, October 2003
题目链接 :http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=649
http://acm.hdu.edu.cn/showproblem.php?pid=1242
题目大意 :天使被囚禁,他(题目给的是个男天使....his...)的小伙伴们去救他,求最短时间,地牢中有墙壁有路有守卫,假设每个守卫都会被击败(这守卫真是垃圾),每击败一个守卫所用时间加1。
题目分析 :这题博主做了2个多小时,我准备把做这题的心路历程写下来,半夜两点半不睡觉在这写博客也是蛮拼的了,开始直接用BFS记录步数,发现样例过了可是wa了,博主脑残,可以忽视...之后改成用与图对应的时间表记录到每个点的最短时间,最后return到所求点的最短时间,样例又过了,也A了,不过是在ZOJ上A的,差点就要写上博客了,准备去HDU再水一发...结果这一水就水了一个多小时,怎么交都是wa,只能说ZOJ的数据太水了,后来发现 (Angel‘s friends),("r" stands for each of Angel‘s friend.)这样两句话,博主当场吐血...都是审题惹的祸...天使那么牛逼,肯定是会有很多小伙伴的呀,没办法,继续改,依旧是用时间记录,多次BFS,结果怎么样?,在HDU不但A了还是0秒飘过,在ZOJ上仍然是30MS,所以这两个OJ上的数据真应该综合一下...看了网上各种版本的题解都是BFS+优先队列,用BFS+优先队列的话要从天使开始找小伙伴,而我的方法则无所谓,下面贴代码,和博主自己刨出来的几组数据
7 8
#.#####.
#a.#xr..
#.x#xx..
#.......
.#......
........
12
4 5
axxxr
..x..
#..x.
rxxr#
6
5 7
#######
#...xx#
#a##xr#
#...xx#
#######
8
#include <cstdio> #include <cstring> #include <queue> using namespace std; int const MAX = 200 + 1; int const INF = 0xffff; char map[MAX][MAX]; int min_t[MAX][MAX]; int dirx[4] = {1,-1,0,0}; int diry[4] = {0,0,-1,1}; int ax, ay, rx, ry; int m, n; struct Point { int x, y; int t; }; int BFS() { queue <Point> q; Point cur; cur.x = rx; cur.y = ry; cur.t = 0; q.push(cur); while(!q.empty()) { cur = q.front(); q.pop(); for(int i = 0; i < 4; i++) { Point next = cur; next.x += dirx[i]; next.y += diry[i]; next.t++; //遇到守卫时间再加1 if(map[next.x][next.y] == 'x') next.t++; if(next.x < 1 || next.x > n || next.y < 1 || next.y > m || map[next.x][next.y] == '#') continue; //若当前时间小于当前点记录的最短时间,则更新改点的最短时间值 //并将该点压入队列 if(next.t < min_t[next.x][next.y]) { min_t[next.x][next.y] = next.t; q.push(next); } } } return min_t[ax][ay]; //返回的为当前朋友到天使处的最短时间 } int main() { int ans; while(scanf("%d%d",&n, &m) != EOF) { ans = INF; memset(map,0,sizeof(map)); for(int i = 1; i <= n; i++) //输入图 { scanf("%s",map[i] + 1); for(int j = 1; j <= m; j++) { min_t[i][j] = INF; //将时间表初始化为最大值 if(map[i][j] == 'a') { ax = i; ay = j; } } } for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(map[i][j] == 'r') //对每一个r都要搜索一遍 { rx = i; ry = j; if(ans > BFS()) ans = BFS(); } if(ans == INF) printf("Poor ANGEL has to stay in the prison all his life.\n"); else printf("%d\n",ans); } }