Nightmare HDU-1072 BFS

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章