POJ 1475 Pushing Boxes

190 篇文章 2 订阅
15 篇文章 0 订阅

题面

题意

给出一副只有一个箱子的推箱子游戏的地图,输出路径.没有则输出"Impossible."
路径要保证箱子移动次数最小,在此条件下,人移动次数最小.

方法

因为求最小次数,故用BFS
因为考虑到要箱子移动次优先,而不是人,故直接搜人怎么移动必然会出错
因而我们可以给每次移动加一个权,人移动的代价是1,箱子是1000,并将结果存储在一个优先队列中,这样就能保证箱子移动次数最少,再用宽搜即可

注意:每输出完一组数据后要空一行.

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define fi first
#define se second
#define PP pair<pair<int,int>,pair<int,int> >
#define P pair<int,PP>
#define people_x fi.fi
#define people_y fi.se
#define box_x se.fi
#define box_y se.se
#define N 1000
using namespace std;

int m,n,px,py,bx,by,zx,zy,nx,ny,nbx,nby,dir[4][2]= {-1,0,1,0,0,-1,0,1},quan,rr,T;
char a[30][30],res[10000],str[25],ans[30][30][30][30];
priority_queue<P,vector<P>,greater<P> >pq;
P tmp,now;
PP pri[30][30][30][30],tmp2,k,start;
bool have,vis[30][30][30][30];

int main()
{
	int i,j,l;
	while(~scanf("%d%d",&m,&n))
	{
		T++;
		if(!m&&!n) return 0;
		have=0;
		memset(vis,0,sizeof(vis));
		while(!pq.empty()) pq.pop();
		for(i=1; i<=m; i++)
		{
			scanf("%s",str+1);
			for(j=1; j<=n; j++)
			{
				a[i][j]=str[j];
				if(a[i][j]=='T')
				{
					zx=i;
					zy=j;
				}
				if(a[i][j]=='B')
				{
					bx=i;
					by=j;
				}
				if(a[i][j]=='S')
				{
					px=i;
					py=j;
				}
			}
		}

		printf("Maze #%d\n",T);
		tmp.first=0;
		tmp2.box_x=bx;
		tmp2.box_y=by;
		tmp2.people_x=px;
		tmp2.people_y=py;
		tmp2;
		tmp.second=tmp2;
		start.fi.fi=start.fi.se=start.se.fi=start.se.se=-1;
		pri[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]=start;
		vis[px][py][bx][by]=1;
		pri[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]=start;
		pq.push(tmp);
		while(!pq.empty()&&!have)
		{
			now=tmp=pq.top();
			pq.pop();
			tmp2=tmp.second;
			bx=tmp2.box_x;
			by=tmp2.box_y;
			px=tmp2.people_x;
			py=tmp2.people_y;
			if(bx==zx&&by==zy)
			{
				rr=0;
				k=tmp2;
				while(pri[k.fi.fi][k.fi.se][k.se.fi][k.se.se]!=start)
				{
					rr++;
					res[rr]=ans[k.fi.fi][k.fi.se][k.se.fi][k.se.se];
					k=pri[k.fi.fi][k.fi.se][k.se.fi][k.se.se];
				}
				for(i=rr; i>=1; i--)
				{
					printf("%c",res[i]);
				}
				printf("\n");
				have=1;
				break;
			}
			for(i=0; i<=3; i++)
			{
				quan=1;
				nx=px+dir[i][0];
				ny=py+dir[i][1];
				nbx=bx;
				nby=by;
				if(a[nx][ny]=='#'||nx<1||nx>m||ny<1||ny>n) continue;
				if(nx==bx&&ny==by)
				{
					nbx+=dir[i][0];
					nby+=dir[i][1];
					quan=N;
				}
				if(a[nbx][nby]=='#'||nbx<1||nbx>m||nby<1||nby>n) continue;
				tmp2.box_x=nbx;
				tmp2.box_y=nby;
				tmp2.people_x=nx;
				tmp2.people_y=ny;
				tmp.second=tmp2;
				tmp.first=now.first+quan;
				if(vis[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y])
					continue;
				vis[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]=1;
				pri[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]=now.second;
				if(i==0) ans[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]= quan==N?'N':'n';
				if(i==1) ans[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]= quan==N?'S':'s';
				if(i==2) ans[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]= quan==N?'W':'w';
				if(i==3) ans[tmp2.people_x][tmp2.people_y][tmp2.box_x][tmp2.box_y]= quan==N?'E':'e';
				pq.push(tmp);
			}
		}
		if(!have)
		{
			printf("Impossible.\n");
		}
		puts("");
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值