迷宫有炸弹,爆炸时间6分钟,迷宫中有炸弹重置器,判断是否能逃出迷宫(若能逃出输出最短路)。
与传统迷宫不同,设置了逃出时间和延长弹出时间的点。依旧采用BFS最短路径搜索,每遇到炸弹重置器,重置时间,并不再访问该点,毫无疑问炸弹无须访问第二次,会做无用功浪费时间。
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 10;
char maze[MAXN][MAXN];
int n, m;
int sx, sy, gx, gy;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
struct node
{
int x, y, step, time;//步数和所剩时间
};
void bfs()
{
queue<node> q;
node t = {sx, sy, 0, 6};//起点步数0剩余时间6
q.push(t);
while (!q.empty())
{
node tmp;
tmp = q.front();
q.pop();
//搜素4个方向
for (int i = 0; i < 4; ++i)
{
t.x = tmp.x + dx[i];
t.y = tmp.y + dy[i];
t.time = tmp.time - 1;
t.step = tmp.step + 1;
if (t.x >= 0 && t.x < n && t.y >= 0 && t.y < m && t.time > 0 && maze[t.x][t.y] != '0')
{
if (t.x == gx && t.y == gy)
{
//到达终点最短输出步数
cout << t.step << endl;
return;
}
if (maze[t.x][t.y] == '4')
{
//重置时间设为墙
t.time = 6;
maze[t.x][t.y] = 0;
}
q.push(t);
}
}
}
cout << "-1\n";
return ;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> m;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
cin >> maze[i][j];
if (maze[i][j] == '2') {sx = i; sy = j;}
else if (maze[i][j] == '3') {gx = i; gy = j;}
}
}
bfs();
}
}
DFS搜索就复杂一些,深度搜索遍及每一个点,在深搜的过程中,时间不足回溯,遇到炸弹重置器重置时间,在搜索的过程中会遇到重置时间后返回,不能使用vis数组的方式判断是否遍历过。因为路径中确实存在有些点访问两次。为了不陷入死循环,与第一次访问该点做出比较,如果此点步数多而且所剩时间少,那就是无用功,可以回溯。当搜索到答案时,ans取每次的最小值。
#include <iostream>
#include <queue>
#include <string>
#include <map>
#include <cstdio>
#include <algorithm>
#define INF 1e8;
using namespace std;
int n, m, maze[10][10], step[10][10], time[10][10], flg, ans;
int sx, sy, gx, gy;
//sum: 步数 t: 所剩时间
void dfs(int x, int y, int sum, int t)
{
//越界墙,返回
if (t <= 0 || maze[x][y] == 0 || x < 0 || x >= n || y < 0 || y >= m) return;
if (x == gx && y == gy)
{
flg = 1;
//取最短路
ans = min(ans, sum);
return ;
}
if (maze[x][y] == 4)
t = 6;
//判断是否做无用功,与上一次访问进行比较步数多,时间少无效
if (sum >= step[x][y] && time[x][y] >= t)
return ;
//记录步数和时间
step[x][y] = sum;
time[x][y] = t;
dfs(x - 1, y, sum + 1, t - 1);
dfs(x + 1, y, sum + 1, t - 1);
dfs(x, y + 1, sum + 1, t - 1);
dfs(x, y - 1, sum + 1, t - 1);
}
int main()
{
int t;
cin >> t;
while (t--)
{
flg = 0;
ans = INF;
cin >> n >> m;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
//格式化
time[i][j] = 0;
step[i][j] = INF;
cin >> maze[i][j];
if (maze[i][j] == 2)
{
sx = i;
sy = j;
}
else if (maze[i][j] == 3)
{
gx = i;
gy = j;
}
}
}
dfs(sx, sy, 0, 6);
if (flg) cout << ans << endl;
else cout << "-1\n";
}
}