【YBT高效进阶】1基础算法/5广度优先搜索/3立体推箱子

【YBT高效进阶】1基础算法/5广度优先搜索/3立体推箱子

内存限制:256 MiB
时间限制:1000 ms
标准输入输出
题目类型:传统
评测方式:文本比较

题目描述

有一个 N*M 的矩阵,每个位置可能是硬地(用 . 表示),易碎地面(用 E 表示),禁地(用 # 表示),起点(用 X 表示),终点(用 O 表示)。

你的任务是操作一个 112 的长方体。

这个长方体在地面上有两种放置方式," 立 " 在地面上( 11的面接触地面)或者 " 躺 " 在地面上( 12的面接触地面)。

在每一步操作中,可以按上下左右的四个键之一。

按下按键之后,长方体向对应的方向沿着棱滚动 90度 。

任意时刻,长方体不能有任何部位接触禁地,并且不能立在易碎地面上。

字符 X 标识长方体的起始位置,地图上可能有一个 X 或者两个相邻的 X。

地图上唯一的一个字符 O 标识目标位置。

求把长方体移动到目标位置(即立在 O 上)所需要的最少步数。

在移动过程中,X 和 O 的表示位置都可以看作是硬地被利用。

输入格式

输入包含多组测试用例。

对于每个测试用例,第一行包括两个整数 n 和 m。

接下来 n 行用来描述地图,每行包括 m 个字符,每个字符表示一块地图的具体状态。

当输入用例 n=0,m=0 时,表示输入终止,且该用例无需考虑。

输出格式

每个用例输出一个整数表示所需的最少步数,如果无解则输出 Impossible。

每个结果占一行。

样例

样例输入
7 7
#######
#..X###
#..##O#
#....E#
#....E#
#.....#
#######
0 0
样例输出
10

数据范围与提示

对于 100% 的数据,有3<=n,m<=500 。

思路

用3个数保存长方体的状态。
2个数表示坐标。
1个数
0:立着
1:横着,(x,y)为右边点的位置
2:竖着,(x,y)为下面点的位置

代码

#include<iostream>
#include<cstdio>
#include<cstring> 
using namespace std;
struct jgt
{
	int x,y,t,s;
};
jgt b[750010];
char a[510][510];
bool d[510][510][3];
int n,m,sx,sy,st,zx,zy,way[3][4][3]={{{-1,0,2},{2,0,2},{0,-1,1},{0,2,1}},{{-1,0,1},{1,0,1},{0,-2,0},{0,1,0}},{{-2,0,0},{1,0,0},{0,-1,2},{0,1,2}}};
void input()
{
	int i,j;
	memset(d,true,sizeof(d));
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			cin>>a[i][j];
	for(i=1;i<=n;i++)//找起点
		for(j=1;j<=m;j++)
			if(a[i][j]=='X')
			{
				if(a[i-1][j]=='X')
				{
					sx=i;
					sy=j;
					st=2;
				}
				else
					if(a[i+1][j]=='X')
					{
						sx=i+1;
						sy=j;
						st=2;
					}
					else
						if(a[i][j-1]=='X')
						{
							sx=i;
							sy=j;
							st=1;
						}
						else
							if(a[i][j+1]=='X')
							{
								sx=i;
								sy=j+1;
								st=1;
							}
							else
							{
								sx=i;
								sy=j;
								st=0;
							}
				return;
			}
	return;
}
void BFS()
{
	int i,l,r,dx,dy,dt;
	d[sx][sy][st]=0;
	b[1].x=sx;
	b[1].y=sy;
	b[1].s=0;
	b[1].t=st;
	for(l=r=1;l<=r;l++)
		for(i=0;i<4;i++)//扩展
		{
			dx=b[l].x+way[b[l].t][i][0];//算出状态
			dy=b[l].y+way[b[l].t][i][1];
			dt=way[b[l].t][i][2];
			if(a[dx][dy]=='O'&&dt==0)//到达终点
			{
				printf("%d\n",b[l].s+1);
				return;
			}
			if((!(a[dx][dy]=='#'||(dt==0&&(dx<1||dx>n||dy<1||dy>m||a[dx][dy]=='E'))||(dt==1&&(dx<1||dx>n||dy<2||dy>m||a[dx][dy-1]=='#'))||(dt==2&&(dx<2||dx>n||dy<1||dy>m||a[dx-1][dy]=='#'))))&&d[dx][dy][dt])//条件
			{
				r++;
				b[r].x=dx;
				b[r].y=dy;
				b[r].t=dt;
				b[r].s=b[l].s+1;
				d[dx][dy][dt]=0;
			}
		}
	printf("Impossible\n");
	return;
}
int main()
{
	for(scanf("%d%d",&n,&m);n||m;scanf("%d%d",&n,&m))
	{
		input();
		BFS();
	}
	return 0;
}
上一篇:ABAP 最简单SMARFORMS


下一篇:秘密通道