看到这一题首先想到的是深搜或者dp,后来深入了解了一下题意,把dp否定了,然后尝试着用深搜去解。但是在模拟的过程中发现深搜的耗费会很大,于是就去网上搜了一下,网上大神是用广搜和优先队列,看了一下代码,有一种茅塞顿开的感觉。
首先,采用map数组模拟墙、路和怪,flag数组存储走的方向,blood数组存储怪的血量;
然后用重载排序的优先队列对当前节点的所有可能节点进行广搜;
到达目的点后,对到达该点的节点进行flag数组的反操作(flag数组存储的是当前点到下一点需要走的x、y值),即进行回溯操作,打表记录路径,再递归打印即可;
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
int m,n,temp;
int map[111][111];//地图
int blood[111][111];//怪的血量
int flag[111][111];//记录走的路径
int dir[4][2]={0,1,1,0,0,-1,-1,0};//能走的4个方向
struct node{
int x;
int y;
int step;
friend bool operator<(node a,node b){
return b.step<a.step;//step小的节点优先出列
}
}now,nnext;
int bfs(){
priority_queue<node>q;//建立优先队列
now.x=1;//因为我把整个地图向右下平移,所以从(1,1)出发
now.y=1;
now.step=0;
map[1][1]=-1;
q.push(now);
while(!q.empty()){
now=q.top();
q.pop();
if(now.x==m&&now.y==n) return now.step;//到达目的点返回
for(int i=0;i<4;i++){//当前节点所有能走的点进行入队(广搜)
nnext.x=now.x+dir[i][0];
nnext.y=now.y+dir[i][1];
if(map[nnext.x][nnext.y]==-1) continue;
nnext.step=now.step+1+map[nnext.x][nnext.y];//不是墙的话将其入队
flag[nnext.x][nnext.y]=i+1;
map[nnext.x][nnext.y]=-1;
q.push(nnext);
}
}
return -1;
}
void output(int x,int y){
int x_next,y_next;
if(flag[x][y]==0) return;
x_next=x-dir[flag[x][y]-1][0];//回溯打印路径
y_next=y-dir[flag[x][y]-1][1];
output(x_next,y_next);
printf("%ds:(%d,%d)->(%d,%d)\n",temp++,x_next-1,y_next-1,x-1,y-1);//因为我把map数组向右下平移,所以所有的节点值减一
while(blood[x][y]--)
printf("%ds:FIGHT AT (%d,%d)\n",temp++,x-1,y-1);
}
int main(){
char str[111];
int ans;
while(~scanf("%d%d",&m,&n)){
memset(map,-1,sizeof(map));//将map的初始值赋-1,为了方便下一步直接留出边界
memset(blood,0,sizeof(blood));
memset(flag,0,sizeof(flag));
for(int i=0;i<m;i++){
scanf("%s",str);
for(int j=0;j<n;j++){
if(str[j]=='.')
map[i+1][j+1]=0;//不对i、j进行操作而对i+1、j+1进行操作,即将map向右下平移,留出一圈值为-1的墙(边界)
else if(str[j]=='X')
map[i+1][j+1]=-1;
else
map[i+1][j+1]=blood[i+1][j+1]=str[j]-'0';
}
}
ans = bfs();
if(ans==-1) printf("God please help our poor hero.\n");
else{
printf("It takes %d seconds to reach the target position, let me show you the way.\n",ans);
temp=1;
output(m,n);
}
printf("FINISH\n");
}
return 0;
}