HDU1254 推箱子
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Submit
Status
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
题解
题目要求的是箱子的最短路,所以用BFS求箱子的最短路,同时也要求人能不能到达箱子的上一个位置,因为人推箱子的时候人是不动的,另外还要注意记录状态的时候要开三维vis[i][j][dir],因为从不同的位置推箱子产生后续的状态也是不同的,另外一点就是箱子走过的路可以再走,注意细节就可以啦
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define LL unsigned long long
using namespace std;
int n,m,T;
int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int str[10][10];
struct Node{
int x,y,step;
int mmap[10][10];
bool check(){
if(x>=0&&x<n&&y>=0&&y<m)
return true;
return false;
}
}s,e,u,v,ss,ee,uu,vv;
bool bfs_people(Node n1){ //搜索人是否能到达指定位置
queue<Node>que;
ss=n1;
bool flag[10][10];
memset(flag,false,sizeof(flag));
for(int i=0;i<n;i++){ //找到人的起点
for(int j=0;j<m;j++)
if(n1.mmap[i][j]==4){
ss.x=i;
ss.y=j;
ss.step=0;
}
}
if(ss.x==ee.x&&ss.y==ee.y)
return true;
que.push(ss);
flag[ss.x][ss.y]=true;
while(!que.empty()){
uu=que.front();
que.pop();
for(int i=0;i<4;i++){
vv=uu;
vv.step++;
vv.x+=way[i][0];
vv.y+=way[i][1];
if(vv.check()&&flag[vv.x][vv.y]==false&&(n1.mmap[vv.x][vv.y]!=1&&n1.mmap[vv.x][vv.y]!=2)){ //目标点不是墙也不是箱子
flag[vv.x][vv.y]=true;
if(vv.x==ee.x&&vv.y==ee.y)
return true;
que.push(vv);
}
}
}
return false;
}
int bfs_box(){ //搜索箱子
int flag[10][10][4];
queue<Node>que;
que.push(s);
memset(flag,false,sizeof(flag));
while(!que.empty()){
u=que.front();
que.pop();
for(int i=0;i<4;i++){
v=u;
v.x+=way[i][0];
v.y+=way[i][1];
v.step++;
if(v.check()&&str[v.x][v.y]!=1&&flag[v.x][v.y][i]==false){
//人的目标位置
ee.x=u.x-way[i][0];
ee.y=u.y-way[i][1];
if(ee.check()==false)
continue;
if(bfs_people(v)){
//更新地图,箱子和人的位置
swap(v.mmap[v.x][v.y],v.mmap[u.x][u.y]);
swap(v.mmap[ee.x][ee.y],v.mmap[ss.x][ss.y]);
flag[v.x][v.y][i]=true;
if(str[v.x][v.y]==3)
return v.step;
que.push(v);
}
}
}
}
return -1;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
scanf("%d",&str[i][j]);
s.mmap[i][j]=str[i][j];
if(str[i][j]==2){ //标注箱子起点
s.x=i;
s.y=j;
s.step=0;
}
}
printf("%d\n",bfs_box());
}
return 0;
}