20180610模拟赛T1——脱离地牢

Description

在一个神秘的国度里,年轻的王子Paris与美丽的公主Helen在一起过着幸福的生活。他们都随身带有一块带磁性的阴阳魔法石,身居地狱的魔王Satan早就想着得到这两块石头了,只要把它们溶化,Satan就能吸收其精华大增自己的魔力。于是有一天他趁二人不留意,把他们带到了自己的地牢,分别困在了不同的地方。然后Satan念起了咒语,准备炼狱,界时二人都将葬身于这地牢里。 危险!Paris与Helen都知道了Satan的意图,他们要怎样才能打败魔王,脱离地牢呢?Paris想起了父王临终前给他的备忘本,原来他早已料到了Satan的野心,他告诉Paris只要把两块魔法石合在一起,念出咒语,它们便会放出无限的光荣,杀死魔王,脱离地牢,而且本子上还附下了地牢的地图,Paris从中了解到了Helen的位置所在。于是他决定首先要找到Helen,但是他发现这个地牢很奇怪,它会增强二人魔法石所带的磁力大小,而且会改变磁力的方向。这就是说,每当Paris向南走一步,Helen有可能会被石头吸引向北走一步。而这个地狱布满了岩石与熔浆,Paris必须十分小心,不仅他不能走到岩石或熔浆上,而且由于他行走一步,Helen的位置也会改变,如果Helen碰到岩石上,那么她将停留在原地,但如果Helen移动到了熔浆上,那么她将死去,Paris就找不到她了。 Paris仔细分析了地图,他找出了一条最快的行走方案,最终与Helen相聚。他们一起念出了咒语“·#¥%^…*&@!”,轰隆一声,地牢塌陷了,他们又重见光明…

Input

输入数据第一行为两个整数n,m(3<=n,m<=20),表示地牢的大小,n行m列。接下来n行,每行m个字符,描述了cf地牢的地图,“.”代表通路,“#”代表岩石,“!”代表熔浆,“H”表示Helen,“P”表示Paris。输入保证地牢是封闭的,即四周均是岩石或熔浆。接下来一行有四个字符“N”(北),“S”(南),“W”(西),“E”(东)的排列,表示Paris分别向NSWE四个方向走时Helen受磁石磁力影响的移动方向。

Output

输出文件只有一行,如果Paris能找到Helen,输出一整数d,为Paris最少需要行走的步数;如果Paris在255步之后仍找不到Helen,则输出“Impossible”。注意相遇是指Paris与Helen最终到达同一个格子,或者二人在相邻两格移动后碰到了一起,而后者的步数算他们移动后的步数。

Sample Input

5 5
#####
#H..#
#.!.#
#.#P#
#####
WNSE

Sample Output

5

题解

话说这几天每次模拟赛怎么都有一道搜索……

裸的bfs。然而交上去只有奇怪的80分,发现是没注意这句话:

注意相遇是指Paris与Helen最终到达同一个格子,或者二人在相邻两格移动后碰到了一起,而后者的步数算他们移动后的步数。

就是如果Paris从A到B,Helen从B到A,那么也算碰到了一起。

于是这个需要判一下。

感觉没什么好讲的了,就直接上代码吧。

#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 25;

int n, m;

char mmap[maxn][maxn];
bool vis[maxn][maxn][maxn][maxn];//直接记录状态

struct sxd//这是机房大佬,请不要在意
{
	int hi, hj, pi, pj;
	int bs;
};

const int diri[] = {-1, 1, 0, 0};
const int dirj[] = {0, 0, -1, 1};
int dirhi[5];
int dirhj[5];

int main()
{
	freopen("escape.in", "r", stdin);
	freopen("escape.out", "w", stdout);
	scanf("%d%d\n", &n, &m);
	sxd first;
	first.bs = 0;
	for(int i = 0; i < n; ++i)
	{
		gets(mmap[i]);
		for(int j = 0; j < m; ++j)
		{
			if(mmap[i][j] == 'H')
			{
				first.hi = i;
				first.hj = j;
				mmap[i][j] = '.';
			}
			else if(mmap[i][j] == 'P')
			{
				first.pi = i;
				first.pj = j;
				mmap[i][j] = '.';
			}
		}
	}
	queue<sxd> Q;
	Q.push(first);
	vis[first.pi][first.pj][first.hi][first.hj] = true;
	char tmp[5];
	gets(tmp);
	for(int i = 0; i < 4; ++i)
	{
		switch(tmp[i])
		{
			case 'W':
				dirhi[i] = 0;
				dirhj[i] = -1;
				break;
			case 'N':
				dirhi[i] = -1;
				dirhj[i] = 0;
				break;
			case 'S':
				dirhi[i] = 1;
				dirhj[i] = 0;
				break;
			case 'E':
				dirhi[i] = 0;
				dirhj[i] = 1;
				break;
		}
	}
	while(!Q.empty())
	{
		sxd now = Q.front();
		Q.pop();
		if(now.bs > 255)
			break;
		for(int i = 0; i < 4; ++i)
		{
			sxd nxt = now;
			nxt.bs++;
			nxt.pi += diri[i];
			nxt.pj += dirj[i];
			nxt.hi += dirhi[i];
			nxt.hj += dirhj[i];
			if(nxt.hi == now.pi && nxt.hj == now.pj && nxt.hj == now.pj && now.hi == nxt.pi)//注意判交错情况
			{
				printf("%d", nxt.bs);
				fclose(stdin);
				fclose(stdout);
				return 0;
			}
			if(mmap[nxt.pi][nxt.pj] != '.' || mmap[nxt.hi][nxt.hj] == '!')
				continue;
			if(mmap[nxt.hi][nxt.hj] == '#')//注意Helen是可以撞墙的。
			{
				nxt.hi = now.hi;
				nxt.hj = now.hj;
			}
			if(nxt.hi == nxt.pi && nxt.hj == nxt.pj)
			{
				printf("%d", nxt.bs);
				fclose(stdin);
				fclose(stdout);
				return 0;
			}
			if(!vis[nxt.pi][nxt.pj][nxt.hi][nxt.hj])
			{
				Q.push(nxt);
				vis[nxt.pi][nxt.pj][nxt.hi][nxt.hj] = true;
			}
		}
	}
	puts("Impossible");
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2018-06-10 18:31  pfy_pfy  阅读(143)  评论(0编辑  收藏  举报