HDU 1254 推箱子(广搜+优先队列)
发布时间:2021年12月06日 20:08:21
发布人:jqh?
**Problem Description**
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.
现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.

**Input**
 
输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
 
 
**Output**
 
对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
 
 
**Sample Input**
 
1 5 5 0 3 0 0 0 1 0 1 4 0 0 0 1 0 0 1 0 2 0 0 0 0 0 0 0
 
 
**Sample Output**
 
4
 
 
**Author**
 
Ignatius.L & weigang Lee
 
```cpp
#include <iostream>
#include <queue>
#include <memory.h>
using namespace std;
struct status
{
    int bx,by;//箱子的坐标
    int px,py;//人的坐标
    int step;
    bool friend operator <(const status& a,const status& b)//重载优先队列的比较符
    {
        return a.step>b.step;
    }
};
int main()
{
    int T,m,n;
    int mmap[10][10];
    int di[4][2]= {-1,0,1,0,0,-1,0,1};
    bool visit_of_person[10][10][10][10];
    priority_queue <status> q;
    //使用优先队列可以使推动箱子次数多的状态推迟出队,从而保证箱子每个能推动的方向都被访问到并推动
   //若直接使用队列,则无法使每种情况都走到
    cin>>T;
    for(int Ti=0; Ti<T; ++Ti)
    {
        memset(visit_of_person,false,10000);
        status start;
        start.step=0;
        int endx,endy;
        int ans=0;
        cin>>m>>n;
        for(int i=0; i<m; ++i)
            for(int j=0; j<n; ++j)
            {
                cin>>mmap[i][j];
                if(mmap[i][j]==2)
                    start.bx=i,start.by=j;
                else if(mmap[i][j]==3)
                    endx=i,endy=j;
                else if(mmap[i][j]==4)
                    start.px=i,start.py=j;
            }
        q.push(start);
        bool found=false;
        while(!q.empty()&&!found)
        {
            for(int i=0; i<4; ++i)
            {
                status cur_status=q.top();
                cur_status.px+=di[i][0];
                cur_status.py+=di[i][1];
                //先判越界,否则可能出现数组下标为负的情况
                if(cur_status.px<0||cur_status.px>=m||cur_status.py<0||cur_status.py>=n)//越界
                    continue;
                if(mmap[cur_status.px][cur_status.py]==1)//走到墙上
                    continue;
                if(visit_of_person[cur_status.bx][cur_status.by][cur_status.px][cur_status.py])//该状态已经走过
                    continue;
                if(cur_status.px==cur_status.bx&&cur_status.py==cur_status.by)//走到箱子上
                {
                    int next_box_x=cur_status.bx+di[i][0];
                    int next_box_y=cur_status.by+di[i][1];
                    if(next_box_x<0||next_box_x>=m||next_box_y<0||next_box_y>=n)//箱子越界
                        continue;
                    if(mmap[next_box_x][next_box_y]==1)//箱子走到墙上
                        continue;
                    //箱子既没走到墙上也没越界,则箱子走一步
                    cur_status.bx=next_box_x;
                    cur_status.by=next_box_y;
                    ++cur_status.step;
                    if(cur_status.bx==endx&&cur_status.by==endy)//箱子走到终点
                    {
                        found=true;
                        ans=cur_status.step;
                    }
                }
                q.push(cur_status);
                visit_of_person[cur_status.bx][cur_status.by][cur_status.px][cur_status.py]=true;
            }
            q.pop();
        }
        if(found)
            cout<<ans<<endl;
        else
            cout<<-1<<endl;
        while(!q.empty())//清空队列
            q.pop();
    }
    return 0;
}
```
			
热门评论: