HDOJ 1254 推箱子 (BFS)

http://acm.hdu.edu.cn/showproblem.php?pid=1254

题意:推箱子游戏,在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,求最少的推箱子的次数,如果不能完成则输出-1。

思路:带嵌套的BFS~第一层BFS箱子,箱子每次移动前要再BFS一下人,看人能不能走到推动箱子的位置。

注意://因为人的位置不同时箱子可能可以到同一个位置两次,所以开4维(两维是箱子位置,两维是人的位置)数组标记。

#include<cstdio>
#include<cstring>
#include<queue>
 
using namespace std;
 
struct node{
	int x,y,cnt;
	int px,py;
}now,tmp,pnow,ptmp;
 
queue<struct node>q;//BFS箱子的队列
queue<struct node>p;//BFS人的队列
 
int m,n;
int maze[11][11];
bool vis[11][11][11][11];
bool pvis[11][11];
 
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
 
bool p_ok()
{
	if(ptmp.x>=0&&ptmp.y>=0&&ptmp.x<m&&ptmp.y<n&&maze[ptmp.x][ptmp.y]!=1&&!(ptmp.x==now.x&&ptmp.y==now.y)&&!pvis[ptmp.x][ptmp.y])
		return true;
	else
		return false;
}
 
bool p_bfs(int k)//简单的BFS,i为箱子要去的方向
{
	while(!p.empty())
		p.pop();
	memset(pvis,false,sizeof(pvis));
	pnow.x=tmp.px;pnow.y=tmp.py;
	if(pnow.x==now.x-dx[k]&&pnow.y==now.y-dy[k])//特殊判断人就在箱子边上且正好是要推箱子的位置的情况
		return true;
	pvis[pnow.x][pnow.y]=true;
	p.push(pnow);
	while(!p.empty())
	{
		pnow=p.front();
		p.pop();
		for(int i=0;i<4;i++)
		{
			ptmp=pnow;
			ptmp.x+=dx[i];
			ptmp.y+=dy[i];
			if(p_ok())
			{
				if(ptmp.x==now.x-dx[k]&&ptmp.y==now.y-dy[k])
					return true;
				pvis[ptmp.x][ptmp.y]=true;
				p.push(ptmp);
			}
		}
	}
	return false;
}
 
bool ok()
{
	if(tmp.x>=0&&tmp.y>=0&&tmp.x<m&&tmp.y<n&&maze[tmp.x][tmp.y]!=1&&!vis[tmp.x][tmp.y][tmp.px][tmp.py])
		return true;
	else
		return false;
}
 
int bfs()
{
	while(!q.empty())
		q.pop();
	now.cnt=0;
	vis[now.x][now.y][now.px][now.py]=true;
	q.push(now);
	while(!q.empty())
	{
		now=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			tmp=now;
			tmp.x+=dx[i];
			tmp.y+=dy[i];
			if(ok())
			{
				if(p_bfs(i))//判断人能否走到要推箱子的位置
				{
					tmp.cnt++;
					if(maze[tmp.x][tmp.y]==3)
						return tmp.cnt;
					tmp.px=now.x;tmp.py=now.y;
					vis[tmp.x][tmp.y][now.px][now.py]=true;
					q.push(tmp);
				}
			}
		}
	}
	return -1;
}
 
int main()
{
	int t;
	while(scanf("%d",&t)==1)
	{
		while(t--)
		{
			memset(vis,false,sizeof(vis));
			scanf("%d %d",&m,&n);
			for(int i=0;i<m;i++)
			{
				for(int j=0;j<n;j++)
				{
					scanf("%d",&maze[i][j]);
					if(maze[i][j]==2){now.x=i;now.y=j;}
					else if(maze[i][j]==4){now.px=i;now.py=j;}//初始化BFS箱子的第一个节点
				}
			}
			printf("%d\n",bfs());
		}
	}
	return 0;
}



知识共享许可协议
作品由 sdc1992创作,采用 知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

基于http://www.sdc1992.com/上的作品创作。

欢迎关注我的新博客:http://www.sdc1992.com/

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值