hdu--1242

Rescue

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 22395    Accepted Submission(s): 7953


Problem Description
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
题目大意:Angel被关起来了,他的朋友们要去救她,每一次只有四个方向可以走,上下左右,每走一步花费1分钟时间.但遇到墙'#'是不可以通行的,遇到警卫'x',只有将它杀死,才能接着这个位置继续路走,杀死警卫也需要1分钟的时间.问能不能将Angel救出,可以的话最少要多少时间.
解题思路: 首先注意的一点是Angel的朋友可能不只一个,所以可以选择求Angel到朋友的最少时间.接着就是遍历问题了.可以用bfs做.但是在这里步数最小并不代表花费的时间最少.一开始我的做法是走过的路都标记,但遇到'r'后并不马上返回,直到无路可走时才结束.后来发现这样走也不是最有解.因为当从'x'走到(i,j)再到'r'的时间(方案一)大于从'.'走到 (i,j)再到'r'的时间(方案二),然而方案一时(i,j)已经标记过了不能再走了.所以结果不是最优解.如果取消标记,就会导致死循环.最后查了资料,发现了一个很好的方法:
定义一个二位数组time[i][j],time[i][j]表示Angel走到(i,j)位置所需要的最少时间;在bfs搜索过程中,从当前位置走到(x,y)时,只有当该种走比之前走到(x,y)位置所花时间更少,才会把当前走到(x,y)位置所表示的状态入队列,否则是不会入队列的.走过的路也无需标记,因为到达(x,y)的最少时间是有下界的,所以就不会造成无限搜索.
代码如下:
/* 最小步数不一定是最优解 */

#include<stdio.h>
#include<string.h>
#include<queue>
#define  INF 0x3f3f3f3f
using namespace std;
struct stu
{
	int x,y,t;
};
stu s;
int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
char mark[210][210];
int time[210][210];
int n,m,ans;
bool check(stu temp)
{
	if(temp.x<0||temp.y<0||temp.x>=n||temp.y>=m||mark[temp.x][temp.y]=='#')
	return false;
	return true;
}
void bfs()
{
   queue<stu>q;
   stu vt,temp;
   time[s.x][s.y]=0;
   q.push(s);
   while(!q.empty())
   {
         vt=q.front();
		 q.pop();
		 for(int i=0;i<4;i++)
		 {
		 	temp.x=vt.x+dis[i][0];
		 	temp.y=vt.y+dis[i][1];
		   if(check(temp))
		 	{
		 		if(mark[temp.x][temp.y]=='r')
		 		{
		 			ans = ans < (vt.t+1) ? ans:(vt.t+1);
		 		}
		 		else
		 		{
		 			if(mark[temp.x][temp.y]=='x')
		 			temp.t=vt.t+2;
		 			else temp.t=vt.t+1;
		 			if(temp.t<time[temp.x][temp.y])
		 			{
		 				time[temp.x][temp.y]=temp.t;
		 				q.push(temp);
		 			}
		 			
		 		}
		 	}
		 	
		 }	
   }
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i=0;i<n;i++)
		{
			getchar();
			for(int j=0;j<m;j++)
			{
				time[i][j]=INF;
				scanf("%c",&mark[i][j]);
				if(mark[i][j]=='a')
				{
					s.x=i;
					s.y=j;
					s.t=0;
				}
			}
		}
		ans=INF;
		bfs();
		if(ans>=INF)
		printf("Poor ANGEL has to stay in the prison all his life.\n");
		else printf("%d\n",ans);
	}
	return 0;
}



 

你可能感兴趣的:(hdu--1242)