题目大意:
地图中的五种元素:0代表墙
1代表空地
2代表人的起点
3代表出口
4代表炸弹的重启器
炸弹只有6秒的时间,地图中的任何地方都可以走多遍,如果遇到4,那么炸弹的时间被重置为6,要求算出人到达出口的最短时间。
解题思路:
BFS+优先队列,只是标志状态的时候应该开一个三维数组,第三维用来标志到达该点炸弹所剩的时间。数据量有点小,优先队列跟一般队列木有区别,优先队列都0ms过了。
代码:
#include
#include
const int MAX=25;
const int inf=0x7fffffff;
using namespace std;
typedef struct node
{
int x,y,time,step;
friend bool operator<(const struct node &n1,const struct node &n2)
{
return n1.step>n2.step;
}
}N;
int n,m;
int Map[MAX][MAX];
bool visited[MAX][MAX][MAX];
int vst[MAX][MAX];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
void init()
{
memset(visited,false,sizeof(visited));
for(int i=0;iQ;
N cur,pre;
pre.x=sx;
pre.y=sy;
pre.time=6;
pre.step=0;
vst[pre.x][pre.y]=0;
Q.push(pre);
while(!Q.empty())
{
pre=Q.top();
Q.pop();
if(pre.x==ex && pre.y==ey)
{
return pre.step;
}
for(int i=0;i<4;i++)
{
cur=pre;
cur.x+=dir[i][0];
cur.y+=dir[i][1];
cur.time--;
cur.step++;
if(cur.x>=1 && cur.x<=n && cur.y>=1 && cur.y<=m
&& Map[cur.x][cur.y]!=0 && visited[cur.x][cur.y][cur.time]==false)
{
if(cur.time>0 && Map[cur.x][cur.y]==4 )
{
visited[cur.x][cur.y][cur.time]=true;
cur.time=6;
Q.push(cur);
vst[cur.x][cur.y]=cur.step;
//visited[cur.x][cur.y]=true;
}
else if(cur.time>0 )
{
visited[cur.x][cur.y][cur.time]=true;
Q.push(cur);
vst[cur.x][cur.y]=cur.step;
//visited[cur.x][cur.y]=true;
}
}
}
}
return -1;
}
int main(void)
{
int cas;
scanf("%d",&cas);
while(cas--)
{
int sx,sy,ex,ey;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&Map[i][j]);
if(Map[i][j]==2)
{
sx=i,sy=j;
Map[i][j]=1;
}
if(Map[i][j]==3)
{
ex=i,ey=j;
Map[i][j]=1;
}
}
int ans=BFS(sx,sy,ex,ey);
printf("%d\n",ans);
}
return 0;
}