【HDU】1254 推箱子(BFS DFS HASH记录走过的状态)

思路:
很容易想到用搜索去做,并且很容易想到在搜箱子的同时要去搜索人能否到达。
并且两个搜索我们在搜索的同时可以看成是独立的。
人搜索能不能到用DFS并且不用回溯,这样速度会更快。因为对于同一点我们只要到一次就可以了,并不要求最短。所以不用回溯。
在搜索箱子能不能到的时候并没有考虑到重复通过一点的问题。但是时候看了题解才恍然大悟,例如在箱子堵住了唯一路口,但要向人那边前进的时候,就需要后退,让人进来,再前进,这时候就需要重复经过一个点,但这种情况下,人和箱子所处的状态以及位置则是唯一的,切记!!那这时候便用hash记录箱子和人的相关坐标 hash[][][][];
AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
int map[10][10];
bool H[10][10][10][10];
int sx, sy, ex, ey, px, py;
int n, m;
int Div[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
bool vis[10][10];


struct box
{
    int bx, by;
    int px, py;
    int h;
    int steps;
    bool friend operator<(box a, box b)
    {
        return a.steps + a.h>b.steps + b.h;
    }
};

bool check(int x, int y)
{
    if (x >= 0 && x < n&&y >= 0 && y < m&&map[x][y] != 1)
        return true;
    return false;
}

bool dfs(int sx, int sy, int ex, int ey)
{
    if (sx == ex&&sy == ey)
        return true;
    for (int i = 0; i < 4; i++)
    {
        int x = sx + Div[i][0];
        int y = sy + Div[i][1];
        if (check(x, y) && !vis[x][y])
        {
            vis[x][y]=1;
            if (dfs(x, y, ex, ey))
                return true;
        }
    }
    return false;
}

int bfs()
{
    memset(H, 0, sizeof(H));
    priority_queue<box> q;
    box p, mid;
    p.bx = sx;
    p.by = sy;
    p.px = px;
    p.py = py;
    p.steps = 0;
    p.h = abs(p.bx - ex) + abs(p.by - ey);
    q.push(p);
    while (!q.empty())
    {
        p = q.top();
        q.pop();
        if (p.bx == ex&&p.by == ey)
            return p.steps;
        for (int i = 0; i < 4; i++)
        {
            mid = p;
            mid.bx += Div[i][0];
            mid.by += Div[i][1];
            mid.px =mid.bx- Div[i][0];
            mid.py = mid.by - Div[i][1];
            int ppx = p.bx - Div[i][0];
            int ppy = p.by - Div[i][1];
            if (check(mid.bx, mid.by) && check(ppx, ppy)&&!H[p.bx][p.by][ppx][ppy])
            {
                memset(vis, 0, sizeof(vis));
                vis[p.bx][p.by] = 1;
                vis[p.px][p.py] = 1;
                if (dfs(p.px, p.py, ppx, ppy))
                {
                    H[p.bx][p.by][ppx][ppy] = 1;
                    mid.steps = p.steps + 1;
                    mid.h = abs(mid.bx - ex) + abs(mid.by - ey);
                    q.push(mid);
                }
            }
        }
    }
    return -1;
}
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++)
        {
            scanf("%d", &map[i][j]);
            if (map[i][j] == 2)
            {
                sx = i;
                sy = j;
            }
            if (map[i][j] == 3)
            {
                ex = i;
                ey = j;
            }
            if (map[i][j] == 4)
            {
                px = i;
                py = j;
            }
        }
        cout << bfs() << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值