推箱子

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值