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;
}
20180610模擬賽T1——脫離地牢