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";
    }
}

发布了51 篇原创文章 · 获赞 19 · 访问量 8292

猜你喜欢

转载自blog.csdn.net/WxqHUT/article/details/99875105