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