1. 程式人生 > >20180610模擬賽T1——脫離地牢

20180610模擬賽T1——脫離地牢

方向 input lose 輸入 pre 後者 map IV 地圖

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——脫離地牢