题目:HDU026
题意:一个迷宫,从左上角走到右下角,只能上下左右,每走一步需要1秒。不能走 ‘X’ ,数字1-9代表有小怪,在这个地方需要对应的1-9秒的时间杀死小怪。问最快需要多少秒,并且将每一秒做什么输出。
因为有小怪,所以使用优先队列可以更简单一点。
难点就在于记录路径,看了一个大佬的,直接用一个数组来存放每一步的方向,然后就可以用递归还原路径。
当然,用一个伪队列也是可以的,就是用一个一维数组来模拟队列,维护头和尾两个指针,前面的代表出队列,后面的代表入队,然后每一个数组元素记录下父节点的下标,因为这个数组没有删除,所以依旧可以用递归还原路径。
#include <bits/stdc++.h>
using namespace std;
struct rode
{
int x,y,step;
bool operator <(const rode &D)const
{
return step>D.step;
}
};
int d[2][4]= {1,-1,0,0,0,0,1,-1};
int direction[110][110]; // 记录方向
int visited[110][110]; // 记录是否到过
char A[110][110]; // A图记录
int N,M;
int init(int x,int y) //判断这一步能不能走
{
if(A[x][y]=='X'||visited[x][y])
return 1;
else if(x<0||x>=N||y<0||y>=M)
return 1;
return 0;
}
int bfs(int x,int y)
{
priority_queue<rode> q; //初始化
while(!q.empty())
q.pop();
memset(visited,0,sizeof(visited));
rode temp,tem;
temp.x=x;
temp.y=y;
temp.step=0;
q.push(temp);
visited[x][y]=1;
while(!q.empty())
{
temp=q.top();
q.pop();
if(temp.x==(N-1)&&temp.y==(M-1))
return temp.step;
for(int i=0; i<4; i++)
{
tem.x=temp.x+d[0][i];
tem.y=temp.y+d[1][i];
tem.step=temp.step+1;
if(init(tem.x,tem.y))
continue;
if(A[tem.x][tem.y]>='1'&&A[tem.x][tem.y]<='9') //如果遇到小怪,就花费对应的时间
tem.step+=A[tem.x][tem.y]-'0';
visited[tem.x][tem.y]=1;
direction[tem.x][tem.y]=i;
q.push(tem);
}
}
return 0;
}
int tt;
void print(int x,int y) //输出路径
{
if(x==0&&y==0)
return;
int a=x-d[0][direction[x][y]];
int b=y-d[1][direction[x][y]];
print(a,b);
printf("%ds:(%d,%d)->(%d,%d)\n",++tt,a,b,x,y);
if(A[x][y]>'0'&&A[x][y]<='9')
{
int blood=A[x][y]-'0';
while(blood--)
{
printf("%ds:FIGHT AT (%d,%d)\n",++tt,x,y);
}
}
}
int main()
{
while(cin>>N>>M)
{
memset(direction,0,sizeof(direction));
for(int i=0; i<N; i++)
for(int j=0; j<M; j++)
cin>>A[i][j];
int t=bfs(0,0);
if(t)
{
tt=0;
printf("It takes %d seconds to reach the target position, let me show you the way.\n",t);
print(N-1,M-1);
}
else
printf("God please help our poor hero.\n");
printf("FINISH\n");
}
return 0;
}