HDU-1254-推箱子
http://acm.hdu.edu.cn/showproblem.php?pid=1254
用两个BFS即可,一是判断人是否能到达箱子的后面,这里需要注意箱子也是移动的;二是判断箱子是否能到达目的地
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int map[10][10]; //0地板,1墙,2箱子,3目的地,4人
int m,n,obx,oby;
struct cam1 //人和箱子的状态
{
int bx,by,px,py;
}box[1005];
struct cam2 //人的状态
{
int px,py;
}peo[1005];
int visit1[8][8];
int visit2[8][8][8][8];
int step[8][8][8][8]; //每一状态的最小步数
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int check(int x,int y)
{
if(0<=x&&x<m&&0<=y&&y<n&&map[x][y]!=1)
return 1;
return 0;
}
int peobfs(int px,int py,int npx,int npy,int bx,int by) //人是否能到达箱子后
{
int i;
int head,tail;
int nnpx,nnpy;
int nnbx,nnby;
memset(visit1,0,sizeof(visit1));
visit1[px][py]=1;
peo[0].px=px;
peo[0].py=py;
head=0;
tail=1;
map[obx][oby]=0; //原来箱子的位置已发生变化
map[bx][by]=2;
nnbx=bx;
nnby=by;
while(head<tail)
{
px=peo[head].px;
py=peo[head].py;
if(px==npx&&py==npy)
{
map[obx][oby]=2; //复原
map[nnbx][nnby]=0;
return 1;
}
for(i=0;i<4;i++)
{
nnpx=px+dir[i][0];
nnpy=py+dir[i][1];
if(check(nnpx,nnpy)&&!visit1[nnpx][nnpy]&&map[nnpx][nnpy]!=2)
{
peo[tail].px=nnpx;
peo[tail].py=nnpy;
visit1[nnpx][nnpy]=1;
tail++;
}
}
head++;
}
map[obx][oby]=2;
map[nnbx][nnby]=0;
return 0;
}
void bfs(int bx,int by,int px,int py)
{
int i;
int head,tail;
int nbx,nby,npx,npy;
memset(visit2,0,sizeof(visit2));
memset(step,0,sizeof(step));
visit2[bx][by][px][py]=1;
head=0;
tail=1;
box[0].bx=bx;
box[0].by=by;
box[0].px=px;
box[0].py=py;
while(head<tail)
{
bx=box[head].bx;
by=box[head].by;
px=box[head].px;
py=box[head].py;
if(map[bx][by]==3) //箱子所在位置
{
printf("%d\n",step[bx][by][px][py]);
return;
}
for(i=0;i<4;i++)
{
nbx=bx+dir[i][0]; //下一步箱子的位置
nby=by+dir[i][1];
npx=bx-dir[i][0]; //人在箱子的后面
npy=by-dir[i][1];
if(check(nbx,nby)&&check(npx,npy)&&peobfs(px,py,npx,npy,bx,by)&&!visit2[nbx][nby][npx][npy])
{
box[tail].bx=nbx;
box[tail].by=nby;
box[tail].px=npx;
box[tail].py=npy;
visit2[nbx][nby][npx][npy]=1;
step[nbx][nby][npx][npy]=step[bx][by][px][py]+1;
tail++;
}
}
head++;
}
printf("-1\n");
return;
}
int main()
{
int i,j;
int t;
int bx,by,px,py;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&m,&n);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==2) //箱子的起始位置
{
bx=i;
by=j;
}
else if(map[i][j]==4) //人的起始位置
{
px=i;
py=j;
}
}
obx=bx;
oby=by;
bfs(bx,by,px,py);
}
return 0;
}