Nightmare
Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The labyrinth has an exit, Ignatius should get out of the labyrinth before the bomb explodes. The initial exploding time of the bomb is set to 6 minutes. To prevent the bomb from exploding by shake, Ignatius had to move slowly, that is to move from one area to the nearest area(that is, if Ignatius stands on (x,y) now, he could only on (x+1,y), (x-1,y), (x,y+1), or (x,y-1) in the next minute) takes him 1 minute. Some area in the labyrinth contains a Bomb-Reset-Equipment. They could reset the exploding time to 6 minutes.
Given the layout of the labyrinth and Ignatius’ start position, please tell Ignatius whether he could get out of the labyrinth, if he could, output the minimum time that he has to use to find the exit of the labyrinth, else output -1.
Here are some rules:
- We can assume the labyrinth is a 2 array.
- Each minute, Ignatius could only get to one of the nearest area, and he should not walk out of the border, of course he could not walk on a wall, too.
- If Ignatius get to the exit when the exploding time turns to 0, he can’t get out of the labyrinth.
- If Ignatius get to the area which contains Bomb-Rest-Equipment when the exploding time turns to 0, he can’t use the equipment to reset the bomb.
- A Bomb-Reset-Equipment can be used as many times as you wish, if it is needed, Ignatius can get to any areas in the labyrinth as many times as you wish.
- The time to reset the exploding time can be ignore, in other words, if Ignatius get to an area which contain Bomb-Rest-Equipment, and the exploding time is larger than 0, the exploding time would be reset to 6.
输入:
3
3 3
2 1 1
1 1 0
1 1 3
4 8
2 1 1 0 1 1 1 0
1 0 4 1 1 0 4 1
1 0 0 0 0 0 0 1
1 1 1 4 1 1 1 3
5 8
1 2 1 1 1 1 1 4
1 0 0 0 1 0 0 1
1 4 1 0 1 1 0 1
1 0 0 0 0 3 0 1
1 1 4 1 1 1 1 1
输出:
4
-1
13
思路:
这是一个简单的广搜题,需要注意的就是’4’这个特殊点,抵达这个点的时候炸弹时间会重置为6,有时候在直走到不了终点的时候,拐弯走一下’4’这个点然后回来便可抵达终点,所以这道题只需要标记’4’这一个点就行(刚开始写并没有标记’4’,导致不出结果改了好久 )。
代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
struct Inof
{
int x;
int y;
int step; //储存步数
int d; //用来储存剩余时间
friend operator < ( Inof a,Inof b) //设定优先级,步数小的优先出列
{
return a.step > b.step;
}
};
int N,M;
bool vis[300][300];
int cx,cy,ex,ey;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
char map[300][300];
bool panding(int x,int y) //判定这个点是否可以走
{
if(x<1||y<1||x>N||y>M)
return 1;
if(vis[x][y])
return 1;
if(map[x][y]=='0')
return 1;
return 0;
}
void fin()
{
memset(vis,0,sizeof(vis)); //初始化布尔数组
}
int bfs()
{
priority_queue<Inof> a;
Inof cur,next;
cur.x=cx;
cur.y=cy;
cur.step=0;
cur.d=6;
a.push(cur); //第一个元素入列
while(!a.empty())
{
cur = a.top();
a.pop();
if(cur.d<1) //这里是一个关键,如果剩余时间小于1,那么抵达终点也离不开迷宫
continue;
if(cur.x==ex&&cur.y==ey) //抵达终点返回最小步数
{
return cur.step;
}
for(int i=0;i<4;i++) //广搜开始
{
int x=cur.x+dx[i];
int y=cur.y+dy[i];
//判断是否可以走,如果剩余时间为1,无论下一步抵达'4'还是终点都无济于事,所以舍弃
if(panding(x,y)||cur.d<=1)
continue;
next.x=x;
next.y=y;
next.step=cur.step+1;
if(map[x][y]=='4') //如果抵达的点是'4'则时间重置,并标记此点
{
next.d=6;
vis[x][y]=1;
}
else
next.d = cur.d-1;
a.push(next); //新元素入列
}
}
return -1; //如果所有可抵达点都已遍序依然没有到达终点返回-1(题设要求)
}
int main()
{
int n;
cin >> n;
while(n--)
{
cin >> N >> M;
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++)
{
cin >> map[i][j];
if(map[i][j]=='2') //记录入口
cx=i,cy=j;
if(map[i][j]=='3')
ex=i,ey=j; //记录出口
}
fin();
int t = bfs();
cout << t << endl;
}
}