hdoj 1254 推箱子(双重搜索)

来源:互联网 发布:淘宝联盟推广资源管理 编辑:程序博客网 时间:2024/06/02 18:31

推箱子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6836    Accepted Submission(s): 1927


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
15 50 3 0 0 01 0 1 4 00 0 1 0 01 0 2 0 00 0 0 0 0
 

Sample Output
4


BFS+BFS!

我写的太乱了,。。好水的代码!  勉强看吧!   附带几组数据

AC code 

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#include<queue>#define mx 10int map[mx][mx];int visit[mx][mx];int d[4][2]={0,1,1,0,0,-1,-1,0};int  n,m,t;int flag;struct node{int x,y,step;}num[100];node  man,box,bbg,ed;void  Getmap(){int i,j;memset(visit,0,sizeof(visit));scanf("%d%d",&n,&m);for(i=0;i<=n+1;i++)//把图进行“1”初始化 for(j=0;j<=m+1;j++)map[i][j]=1; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&map[i][j]); if(map[i][j]==2) { bbg.x =i;bbg.y =j;bbg.step =0;}else if(map[i][j]==3) { ed.x =i;ed.y=j;}else if(map[i][j]==4){man.x =i;man.y =j;} }}int  bfs2(node s,node e,node b)//判断人 是否能到达推箱子的地点! {if(s.x ==e.x &&s.y ==e.y ){return  1;    }int visitm[mx][mx];memset(visitm,0,sizeof(visitm));int i,j,k;queue<node>q;node a,temp;a=s;q.push(a);visitm[a.x ][a.y]=1;while(!q.empty() ){a=q.front() ;q.pop();if(a.x ==e.x&&a.y ==e.y){return  1;}for(i=0;i<4;i++){ temp.x =a.x +d[i][1];temp.y =a.y +d[i][0];if(map[temp.x ][temp.y ]!=1&&(temp.x!=b.x ||temp.y!=b.y  ||(temp.x !=b.x &&temp.y !=b.y ))&&!visitm[temp.x ][temp.y ]){visitm[temp.x ][temp.y]=1;q.push(temp);}}} return  0;}bool judge(node a,int mark)//判断箱子是否能走这个方向 {int tx=a.x ;int ty=a.y ;node mm;int t1=d[mark][1],t2=d[mark][0];if(t1==1&&t2==0)//判断箱子将要遍历的方向的坐标 {mm.x =tx-1;mm.y =ty;}else if(t1==0&&t2==1){mm.x =tx;mm.y=ty-1;}else if(t1==-1&&t2==0){mm.x =tx+1;mm.y =ty;}else if(t1==0&&t2==-1){mm.x =tx;mm.y =ty+1;}int tx1=tx+d[mark][1] ,ty1=ty+d[mark][0];int tx2=tx+d[(mark+2)%4][1],ty2=ty+d[(mark+2)%4][0];if(visit[tx1][ty1]<m*n)//每个点箱子 可以重复走,但不能无限次,最多n*m次! if(map[tx1][ty1]!=1&&map[tx2][ty2]!=1)//该方向是否能走,在于:该方向前面和后面均没有阻碍 ! {if(bfs2(man,mm,a)) return  1;//判断人是否能到达进行推箱子的地点 }        return  0;}int  bfs1()//对箱子的位置进行遍历 {int i,j,k;queue<node>Q;node a,temp;a=bbg;Q.push(a);visit[a.x ][a.y]++;while(!Q.empty() ){a=Q.front();Q.pop();for(i=0;i<4;i++){temp=a;if(judge(temp,i)){temp.x =a.x +d[i][1];temp.y=a.y +d[i][0];temp.step =a.step +1;if(temp.y==ed.y &&temp.x==ed.x )return temp.step ;visit[temp.x ][temp.y ]++;Q.push(temp); }} man=a;}return  -1;}int main(){    scanf("%d",&t);while(t--){Getmap();int ans=bfs1();printf("%d\n",ans);}} //100//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//4 4//1 2 1 1//0 0 0 0//0 4 3 0//0 0 0 0//4 4//0 3 0 0//0 0 2 0//0 0 4 0//0 1 0 1//3 3//0 3 0//1 0 2//0 4 0//5 5//0 1 4 0 0//0 1 1 1 1//0 2 3 0 0//0 0 0 0 0//0 0 0 0 0//4 4//0 1 0 1//0 2 0 4//0 0 0 0//0 3 0 1////3//3 3//4 0 0//0 2 0//3 0 0//7 4//0 0 0 0//0 0 1 0//0 2 0 3//1 4 1 0//1 0 1 0//1 0 1 0//1 0 0 0



0 0
原创粉丝点击