这是一道十分值得一做的搜索题。题目大意:伊格醒来发现自己在一个安装有定时炸弹的二维迷宫,为了逃离,他必须在迷宫爆炸之前走出迷宫。定时炸弹初始的时间是六分钟,伊格一分钟只能上下左右走一格,并且不能走墙也不能穿过边界。迷宫里有一种重置定时炸弹时间的装置可以使定时炸弹的时间初始为六分钟,只要当前格子有重置器就可以重置定时炸弹。地图中1代表墙,2代表起点,3代表迷宫出口,4代表这个地方有重置器。现在的问题是伊格能否在炸弹爆炸前逃出迷宫(到达出口时炸弹时间为0算未成功逃出迷宫),如果能请输出到达迷宫出口花费的最小时间,不能则输出-1。
我的解题思路:首先求最短的时间,用BFS做,然后这里有重置时间这种装置,我把到每一个点时的剩余时间设一个变量,那么每走一步变量就减一,到达重置装置时剩余时间置为6。因为我们要求出到达终点的最短时间,而炸弹只要还没爆炸就行了,所以我用vis数组存储到达该点的最短时间,初始vis数组全部置为-1。另外,我们要把重置器位置标记,当使用过之后就不能使用了,这样就防止了无限BFS。每到一个点都判断当前时间是否比vis短,是的话就把vis置为当前时间,当然如果vis是-1的话就直接赋值了。最后,当剩余时间为1时还没有到达终点或者未使用过的重置器点,我们就要停止继续搜索了,因为无论怎么走下一步都要爆炸了、、、
接下来是我的解题代码:BFS解题
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
#define N 10
struct point //定义点结构体
{
int x, y; //坐标
int remain; //爆炸剩余时间
int step; //已经花费的时间,也就是步数
};
int n, m, t;
int map[N][N];
int vis[N][N]; //存储到达当前点所花费的最少时间
point start, end; //起点和终点
queue <point> q;
void Read(); //输入
void Init(); //初始化
void DataProcess(); //Bfs解题
int main()
{
scanf("%d", &t);
while (t--)
{
Read();
Init();
DataProcess();
}
return 0;
}
void Read()
{
int i, j;
scanf("%d %d", &n, &m);
for (i=0; i<n; ++i)
{
for (j=0; j<m; ++j)
{
scanf("%d", &map[i][j]);
}
}
return;
}
void Init()
{
int i, j;
for (i=0; i<n; ++i)
{
for (j=0; j<m; ++j)
{
vis[i][j] = -1;
if (map[i][j] == 2)
{
start.x = i;
start.y = j;
}
else if (map[i][j] == 3)
{
end.x = i;
end.y = j;
}
}
}
start.step = vis[start.x][start.y] = 0;
start.remain = 6;
q.push(start);
return;
}
void DataProcess()
{
point a, b;
while (!q.empty())
{
a = q.front();
q.pop();
if (a.remain == 1) continue; //剩余时间为1就不继续在这个节点搜索了
if (a.x + 1 < n && map[a.x+1][a.y] != 0)
{
b = a;
b.x = a.x + 1;
b.step++;
b.remain--;
if (map[b.x][b.y] == 4 && vis[b.x][b.y] == -1) b.remain = 6; //只有当重置器没有使用过的时候才能重置
if (vis[b.x][b.y] == -1 || vis[b.x][b.y] > b.step) vis[b.x][b.y] = b.step;
q.push(b);
}
if (a.x - 1 >= 0 && map[a.x-1][a.y] != 0)
{
b = a;
b.x = a.x - 1;
b.step++;
b.remain--;
if (map[b.x][b.y] == 4 && vis[b.x][b.y] == -1) b.remain = 6;
if (vis[b.x][b.y] == -1 || vis[b.x][b.y] > b.step) vis[b.x][b.y] = b.step;
q.push(b);
}
if (a.y + 1 < m && map[a.x][a.y+1] != 0)
{
b = a;
b.y = a.y + 1;
b.step++;
b.remain--;
if (map[b.x][b.y] == 4 && vis[b.x][b.y] == -1) b.remain = 6;
if (vis[b.x][b.y] == -1 || vis[b.x][b.y] > b.step) vis[b.x][b.y] = b.step;
q.push(b);
}
if (a.y - 1 >= 0 && map[a.x][a.y-1] != 0)
{
b = a;
b.y = a.y - 1;
b.step++;
b.remain--;
if (map[b.x][b.y] == 4 && vis[b.x][b.y] == -1) b.remain = 6;
if (vis[b.x][b.y] == -1 || vis[b.x][b.y] > b.step) vis[b.x][b.y] = b.step;
q.push(b);
}
}
printf("%d\n", vis[end.x][end.y]); //最后直接输出vis就可以得到答案了
return;
}