**Problem Description** 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动. 现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格. ![图示](https://img-blog.csdnimg.cn/img_convert/9cd43be9c80ad0a119b921c7d0d1855d.png) **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; } ```