題目中描述的是走過的路徑還可以重新再走,也就是說走過的路徑不需要標記。但是當遇到重設爆炸時間的點需要標記,不能再從這裏經過。如果遇到爆炸點不標記的話,那麼這個點就可以無限次數的走,剩餘時間會被重設爲6,那麼剩餘時間永遠都不會消耗完,那麼這個程序也就成了一個死循環。
#include <queue>
#include <string.h>
#include <iostream>
using namespace std;
#define MAXN 10
//定義方向,頂部開始,順時針
int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
int n, m;
int a[MAXN][MAXN];
int vis[MAXN][MAXN];
int startX, startY; //開始位置
int endX, endY; //結束位置
struct Node
{
int x;
int y;
int leftTime; //剩餘時間
int cnt; //走到當前位置共走了多少步
}now, nextStep;
//判斷結點能否通過
bool isPracticable(Node node)
{
//當超出邊界,或者剩餘時間爲0,或者遇到障礙物都不能再通過
if (node.x < 0 || node.x > n || node.y < 0 || node.y > m || node.leftTime <= 0 || a[node.x][node.y] == 0 || vis[node.x][node.y]) {
return 0;
}
return 1;
}
int BFS()
{
memset(vis, 0, sizeof(vis));
queue<Node> Q;
now.x = startX;
now.y = startY;
now.leftTime = 6;
now.cnt = 0;
Q.push(now);
while (!Q.empty()) {
//獲取隊列首部元素
now = Q.front();
if (now.x == endX && now.y == endY) {
return now.cnt;
}
for (int i = 0; i < 4; i++) { //按照上、右、下、左的方向搜索,搜索方向可隨意,但是要保證四個方向都被搜索一遍
nextStep.x = now.x + dir[i][0];
nextStep.y = now.y + dir[i][1];
nextStep.cnt = now.cnt + 1;
nextStep.leftTime = now.leftTime - 1;
if (isPracticable(nextStep)) {
if (a[nextStep.x][nextStep.y] == 4) {
nextStep.leftTime = 6; //當走到重設爆炸時間點的時候,把剩餘時間重新設置爲6
vis[nextStep.x][nextStep.y] = 1; //把能夠重新設置爆炸時間的位置標記爲1,此處只能走一次
}
Q.push(nextStep);
}
}
//把對首元素排出隊列
Q.pop();
}
return -1;
}
int main(int argc, const char * argv[]) {
int T;
cin >> T;
while (T--) {
cin >> n >> m;
memset(a, 0, sizeof(a));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
if (a[i][j] == 2) { //記錄開始點
startX = i;
startY = j;
} else if (a[i][j] == 3) { //記住結束點
endX = i;
endY = j;
}
}
}
cout << BFS() << endl;
}
return 0;
}