Pushing Boxes[POJ1475](双重bfs)

本文介绍了一种使用双重BFS算法解决迷宫中推箱子问题的方法,通过分别对盒子和人的移动路径进行搜索,找到从当前位置到目标位置的最短路径。文章详细解释了算法思路,并提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面描述

建议去做加强版poj1475 机翻吧。

思路

由于人和盒子是分开的,我们便想到双重 b f s bfs bfs
在枚举盒子怎么走时,我们可以知道人在哪个方向推这个盒子
然而人现在的位置并不是人在推的位置上,他需要走过来
所以我们需要确定从现在人的位置到要推盒子的位置的最短距离以及路径
所以我们可以 b f s bfs bfs盒子移动的路径时,在进行对人的 b f s bfs bfs

代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
const int N=31;
const char A[4]={'N','S','W','E'};
const char a[4]={'n','s','w','e'};
const int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct node
{
	int x,y,px,py;
	string ans;
};
int n,m;
char s[N][N];
string tmp;
bool pd(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&s[x][y]!='#';}
bool bfs2(node p1,node p2)
{
	tmp="";
	node st;bool v[N][N];memset(v,false,sizeof(v));
	st.x=p1.px,st.y=p1.py;st.ans="";
	queue<node>q;q.push(st);
	while(!q.empty())
	{
		node now=q.front();q.pop();
		if(now.x==p1.x&&now.y==p1.y)
		{
			tmp=now.ans;
			return 1;
		}
		for(int i=0;i<4;i++)
		{
			node nxt=now;
			nxt.x+=d[i][0];nxt.y+=d[i][1];
			if(!pd(nxt.x,nxt.y))continue;
			if(nxt.x==p2.x&&nxt.y==p2.y)continue;
			if(v[nxt.x][nxt.y])continue;
			nxt.ans+=a[i];v[nxt.x][nxt.y]=true;
			q.push(nxt);
		}
	}
	return 0;
}
string bfs1()
{
	node st,ed;st.x=-1,st.px=-1;st.ans="";
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m&&(st.x==-1||st.px==-1);j++)
		{
			if(s[i][j]=='B')
				st.x=i,st.y=j,s[i][j]='.';
			else if(s[i][j]=='S')
				st.px=i,st.py=j,s[i][j]='.';
		}
	}
	bool v[N][N][4];memset(v,false,sizeof(v));
	string ans="Impossible.";int cntans=1e9,cnt=1e9;
	queue<node>q;q.push(st);
	while(!q.empty())
	{
		node now=q.front();q.pop();
		if(s[now.x][now.y]=='T')
		{
			int cntnow=0;
			for(int i=0;i<now.ans.length();i++)
				if(now.ans[i]>='A'&&now.ans[i]<='Z')cntnow++;
			if(cntnow<cntans||(cntnow==cntans&&now.ans.length()<cnt))
			{
				cntans=cntnow;
				ans=now.ans;cnt=now.ans.length();
			}
			continue;
		}
		for(int i=0;i<4;i++)
		{
			node nxt=now;
			nxt.x+=d[i][0];
			nxt.y+=d[i][1];
			if(!pd(nxt.x,nxt.y))continue;
			if(v[nxt.x][nxt.y][i])continue;
			node prv=now;
			if(i==3)prv.y=now.y-1;
			else if(i==2)prv.y=now.y+1;
			else if(i==1)prv.x=now.x-1;
			else prv.x=now.x+1;
			if(!bfs2(prv,now))continue;
			v[nxt.x][nxt.y][i]=true;
			nxt.ans=now.ans+tmp;
			nxt.ans+=A[i];
			nxt.px=now.x;
			nxt.py=now.y;
			q.push(nxt);
		}
	}
	return ans;
}
int num;
void pre()
{
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	printf("Maze #%d\n",++num);cout<<bfs1()<<endl<<endl;
}
int main()
{
	num=0;while(scanf("%d%d",&n,&m)&&n&&m)pre();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值