5 6 .XX.1. ..X.2. 2...X. ...XX. XXXXX. 5 6 .XX.1. ..X.2. 2...X. ...XX. XXXXX1 5 6 .XX... ..XX1. 2...X. ...XX. XXXXX.
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) FINISH It 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) FINISH God please help our poor hero. FINISH
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; // 开始时间为0 q.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(); //强大的bfs if(!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:个人感觉自己的代码可读性还是很强的,变量都定义的很清楚,没有乱定义。。
HDU 1026 Ignatius and the Princess I
原文地址:http://blog.csdn.net/sky_miange/article/details/43731457