HDU 1026 Ignatius and the Princess I

来源:互联网 发布:linux isolinux.cfg 编辑:程序博客网 时间:2024/06/03 18:35
Problem Description
The Princess has been abducted by the BEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now he gets into feng5166's castle. The castle is a large labyrinth. To make the problem simply, we assume the labyrinth is a N*M two-dimensional array which left-top corner is (0,0) and right-bottom corner is (N-1,M-1). Ignatius enters at (0,0), and the door to feng5166's room is at (N-1,M-1), that is our target. There are some monsters in the castle, if Ignatius meet them, he has to kill them. Here is some rules:

1.Ignatius can only move in four directions(up, down, left, right), one step per second. A step is defined as follow: if current position is (x,y), after a step, Ignatius can only stand on (x-1,y), (x+1,y), (x,y-1) or (x,y+1).
2.The array is marked with some characters and numbers. We define them like this:
. : The place where Ignatius can walk on.
X : The place is a trap, Ignatius should not walk on it.
n : Here is a monster with n HP(1<=n<=9), if Ignatius walk on it, it takes him n seconds to kill the monster.

Your task is to give out the path which costs minimum seconds for Ignatius to reach target position. You may assume that the start position and the target position will never be a trap, and there will never be a monster at the start position.
 

Input
The input contains several test cases. Each test case starts with a line contains two numbers N and M(2<=N<=100,2<=M<=100) which indicate the size of the labyrinth. Then a N*M two-dimensional array follows, which describe the whole labyrinth. The input is terminated by the end of file. More details in the Sample Input.
 

Output
For each test case, you should output "God please help our poor hero." if Ignatius can't reach the target position, or you should output "It takes n seconds to reach the target position, let me show you the way."(n is the minimum seconds), and tell our hero the whole path. Output a line contains "FINISH" after each test case. If there are more than one path, any one is OK in this problem. More details in the Sample Output.
 

Sample Input
5 6.XX.1...X.2.2...X....XX.XXXXX.5 6.XX.1...X.2.2...X....XX.XXXXX15 6.XX.....XX1.2...X....XX.XXXXX.
 

Sample Output
It takes 13 seconds to reach the target position, let me show you the way.1s:(0,0)->(1,0)2s:(1,0)->(1,1)3s:(1,1)->(2,1)4s:(2,1)->(2,2)5s:(2,2)->(2,3)6s:(2,3)->(1,3)7s:(1,3)->(1,4)8s:FIGHT AT (1,4)9s:FIGHT AT (1,4)10s:(1,4)->(1,5)11s:(1,5)->(2,5)12s:(2,5)->(3,5)13s:(3,5)->(4,5)FINISHIt takes 14 seconds to reach the target position, let me show you the way.1s:(0,0)->(1,0)2s:(1,0)->(1,1)3s:(1,1)->(2,1)4s:(2,1)->(2,2)5s:(2,2)->(2,3)6s:(2,3)->(1,3)7s:(1,3)->(1,4)8s:FIGHT AT (1,4)9s:FIGHT AT (1,4)10s:(1,4)->(1,5)11s:(1,5)->(2,5)12s:(2,5)->(3,5)13s:(3,5)->(4,5)14s:FIGHT AT (4,5)FINISHGod please help our poor hero.FINISH
 

Author

Ignatius.L

 

做完这道题,感觉到特别的兴奋。10天了,终于把这道题搞出来了。。刚开始看这道题,一点思路都没有,看网上的代码也根本看不懂。

后来每天都有在这道题上思考。终于,前天学了递归输出路径之后,昨晚又在想这道题,还是没搞出来。今天早上就开始写了。开始慢慢的调试。

终于,经过无数次失败的尝试,加上考虑了各种情况,被我一A了。全程没有看任何他人代码。

越来越感觉,很多东西都是在写了之后调试之后才懂得哪里错了,哪里的情况没考虑。

这道题的解析写的详细点。来纪念我十天的青春!!!!(终于救出了另一个公主)

题意:给你一副地图,问从左上角到右下角最短的时间。

并且输出路径。

‘X’代表墙,‘.’代表能走的路。

数字代表有怪物,并且数字是多少就要打几秒。

OK 上代码。

#include <stdio.h>#include <string.h>#include <queue>#include <stack>#include <algorithm>using namespace std;struct node{int x,y;  //坐标int time; //时间friend bool operator<(node a,node b)//  优先队列{ return a.time>b.time;   // 时间小的优先极高}};int n,m;int ans;node pre[105][105];   //   这个数组极为重要,是记录前一步的路径int fight[105][105];  //   这个数组是后面才加上去的。。char map[105][105];   //    地图int vis[105][105];   //   这个数组写在这里,但是貌似没啥用处。int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};  //  方向bool check(int x1,int y1){if(x1<0 || y1<0 || x1>=n || y1>=m || map[x1][y1]=='X')  //排除越界的情况return 0;  return 1;};int Time;   //   这是计时的用的,第1,2,3,N秒。void find(node now)   //   这里非常的关键。。用递归输出路径。{int i;if(now.x==0 &&now.y==0)return;    //    从后面倒回来find(pre[now.x][now.y]);   //  递归输出路径。if(fight[pre[now.x][now.y].x][pre[now.x][now.y].y])   // 这个也是后来才加进去的,战斗数组。也是随意扔进去一个坐标,就对了。  {for(i=0;i<fight[pre[now.x][now.y].x][pre[now.x][now.y].y];i++)printf("%ds:FIGHT AT (%d,%d)\n",++Time,pre[now.x][now.y].x,pre[now.x][now.y].y);  //用个循环写战斗在第几秒}printf("%ds:(%d,%d)->(%d,%d)\n",++Time,pre[now.x][now.y].x,pre[now.x][now.y].y,now.x,now.y);//pre是当前的路径,now是下一步的路径,我在find()里面调试了很久很久,弄了各种输出,发现只有这种输出是对的。}void bfs(){priority_queue<node>q;   //入队。node st,ed;int i;st.x=0;  //  从(0,0)点出发st.y=0;  //  从(0,0)点出发st.time=0;  //  开始时间为0q.push(st);while(!q.empty()){st=q.top();//优先队列的这里是top。不要问为什么,just do it。q.pop();if(st.x==n-1 &&st.y==m-1){ans=st.time;//   要是到达右下角,赋值给ans。(ans一开始为0)break;   }for(i=0;i<4;i++){ed.x=st.x+dir[i][0];ed.y=st.y+dir[i][1];if(!check(ed.x,ed.y))continue;     //如果越界或碰到墙,返回继续。ed.time=st.time+1;  //时间加一。if(map[ed.x][ed.y]>='0' &&map[ed.x][ed.y]<='9'){ed.time+=map[ed.x][ed.y]-'0'; //加上战斗的时间                fight[ed.x][ed.y]=map[ed.x][ed.y]-'0';  //后面加上去的一个战斗数组,注意要减掉‘0’才是阿拉伯的数字}map[ed.x][ed.y]='X';  //这也是一个小技巧吧,变为墙,上面vis标记数组就用不到了,墙是不可走的。pre[ed.x][ed.y]=st;  //   这个也是非常重要,记录前一步的路径。q.push(ed);}}if(ans)//如果ans不为0,说明成功救出了公主。{printf("It takes %d seconds to reach the target position, let me show you the way.\n",ans);  //先输出个花了多少秒逃离。find(st);  //  然后find(st),就可以轻松输出路径了,但突然感觉不对,因为第二个案例的最后一秒的情况并没有输出来。}else return;  // 为0直接回到主函数}int main(){int i,j,final; //final是用来弄最后一秒的状态的。因为上面的代码输出不了最后一秒的状态,所以后来又加了个final。while(scanf("%d%d",&n,&m)!=EOF){final=0; //初始化for(i=0;i<n;i++)scanf("%s",map[i]);if(map[n-1][m-1]>='0' &&map[n-1][m-1]<='9')final=map[n-1][m-1]-'0';   //这个是最后加进来的,一开始是加到下面的else里面去的,发现还是输出不了最后一秒的情况,想了想,原因是把数字变成‘X’(墙)了memset(fight,0,sizeof(fight));ans=0;  // 初始化Time=0;   // 初始化map[0][0]='X';  //  一开始就在这点,变成墙bfs();   //强大的bfsif(!ans)printf("God please help our poor hero.\n");  //如果ans为0说明没救出公主else {for(i=0;i<final;i++)printf("%ds:FIGHT AT (%d,%d)\n",++Time,n-1,m-1); //上面的情况都输完了,考虑最后一步的情况。}printf("FINISH\n");  //完成。。。}}//PS:个人感觉自己的代码可读性还是很强的,变量都定义的很清楚,没有乱定义。。


 

0 0