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写了好久,思路很明显,但是奈何搜索写的太少,很多细节让我一直错。1.解决搜索时人走的路的标记2.解决搜索时箱子走的路的标记3.解决搜索中箱子和人位置的变换我写的人用深搜,箱子用广搜。却W,过不了,具体那错,我还没找到;下面是正确代码,用两个广搜。#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n,m; bool flag,vv[10][10]; int map[10][10]; int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; 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,t,w,mm,man,mans; int dfs(int a,int b){ if(flag) return 1; if(map[a][b]==4){ flag=true;return 1; }//printf("%d,%d---",a,b); for(int j=0;j<4;j++){ mm.x=a+dir[j][0]; mm.y=b+dir[j][1]; if(mm.check()&&!vv[mm.x][mm.y]&&map[mm.x][mm.y]!=1&&map[mm.x][mm.y]!=2){ vv[mm.x][mm.y]=true; dfs(mm.x,mm.y); vv[mm.x][mm.y]=false; } } } int bfs(){ bool v[10][10][4]; memset(v,false,sizeof(v)); queue<node>qu; qu.push(s); while(!qu.empty()){ t=qu.front(); qu.pop(); for(int i=0;i<4;i++){ w=t; w.x=t.x+dir[i][0]; w.y=t.y+dir[i][1]; w.step++; if(w.check()&&!v[w.x][w.y][i]&&map[w.x][w.y]!=1){ man.x=t.x-dir[i][0]; man.y=t.y-dir[i][1]; if(man.check()){ flag=false; memset(vv,false,sizeof(vv)); dfs(man.x,man.y); if(flag){ swap(w.mmap[w.x][w.y],w.mmap[t.x][t.y]); swap(w.mmap[man.x][man.y],w.mmap[mans.x][mans.y]); v[w.x][w.y][i]=true; //printf("%d,%d-->>%d,%d_%d\n",t.x,t.y,w.x,w.y,w.mmap[w.x][w.y]); if(map[w.x][w.y]==3) return w.step; qu.push(w); } } } } } 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",&map[i][j]); if(map[i][j]==2){ s.x=i; s.y=j; s.step=0; } if(map[i][j]==4){ mans.x=i; mans.y=j; } } printf("%d\n",bfs()); } }
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,m,T; int dir[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(node p){ //搜索人是否能到达指定位置 queue<node>que; ss=p; bool flag[10][10]; memset(flag,false,sizeof(flag)); for(int i=0;i<n;i++){ //找到人的起点 for(int j=0;j<m;j++) if(p.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+=dir[i][0]; vv.y+=dir[i][1]; if(vv.check()&&flag[vv.x][vv.y]==false&&(p.mmap[vv.x][vv.y]!=1&&p.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(){ //搜索箱子路径 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+=dir[i][0]; v.y+=dir[i][1]; v.step++; if(v.check()&&str[v.x][v.y]!=1&&flag[v.x][v.y][i]==false){//目标点不是墙 ee.x=u.x-dir[i][0]; //人的目标位置 ee.y=u.y-dir[i][1]; if(ee.check()){ //不越界 if(bfs(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()); } return 0; }
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