迷宮有炸彈,爆炸時間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";
}
}