Problem D
The Great Escape
Poor Kianoosh! 6 weeks since he was officially accepted as a citizen of Barareh and during this time he has had nothing but Nochophskew for his breakfast, lunch and dinner. And nowadays, during the nights, he dreams of nothing but a small piece of bread, some cheese and a glass of milk to have for his breakfast. And during the days, he thinks of nothing but a great escape from this weird city in order to turn his night-time dreams into reality.
After carefully checking all the potential ways out of the city, he concluded that there are only three such possible ways. The first one is through the city gate which is of course guarded by fully-armed guards, ready to kill any creature trying to go through the gate without permission. The second way is passing through the northern walls of the city and going through a jungle which contains nothing but those deadly snakes called NeshimanGazes (And be sure that Kianoosh does not like to repeat his creepy experience with them again).
Finally, the third and the last (and of course the only feasible) way is passing through a secret door in the famous so called HezarDaroon Castle (means a castle with thousands of doors). Unfortunately, the problem with this castle is that no one actually knows the way to reach this secret door.
After spending some time gathering information about the castle, Kianoosh found out that HezarDaroon can actually be modeled as an grid with each cell representing a room in the castle. There is always a door between two neighboring rooms but there are some rooms which contain a NeshimanGaz ready to serve anyone trying to enter the room with its poisonous bites.
There are also some rooms which contain a rotating door. A rotating door is actually a cylinder positioned at the center of the room with a slice removed from it. In Figure 1, you can see a room with a rotating door with its removed slice facing towards west.
Figure 1. A Rotating Door
As it can be seen, one can only enter the room from the neighbor to which the removed slice is facing. And once Kianoosh enters the room, he can rotate the door clockwise or counter-clockwise in order to reach the other doors in the room. For example, in the configuration of figure 1, if he rotates the door clockwise by 90 degrees, he can reach the door to the north and if he continues rotating the door by another 90 degrees in the same direction, he can reach the door to east.
Another important fact about the rotating doors is that associated to each door is a number which is the amount of time, measured in seconds, that it takes for a normal human-being(like Kianoosh) to rotate the door by 90 degrees. You may also assume that going from a room to its neighbor room takes exactly 1 second.
Today, after spending a noticeable amount of money, Kianoosh managed to buy a map of the castle from underground shops of Barareh. Taking a look at the map, he found that the entrance to the castle is located at the lower-left corner and the secret door is located at the upper-right corner of the grid. He can also see the position and the initial configuration of the rotating doors and the coordinates of rooms containing the deadly NeshimanGazes to which Kianoosh does not like to enter.
Kianoosh is happy. He is only one step away from his dreams coming true. But how can he find his way to the secret door? Yes! He needs help! And as a genius problem-solver, you should help him find the path with the minimum required time to reach the secret passage from the lower-left corner of the castle.
The Input
The first line of the input contains an integer which is the number of test cases. Each test case begins with a line containing
(the number of rows) and
(the number of columns) followed by
lines, with the
th line containing
characters, the
th character of which representing the status of the
th cell in the
th row of the grid (counted from north). Each character may have six different values. A ‘.’ character represents a normal room while a ‘#’ represents a room containing a NeshimanGaz and ‘N’, ‘W’, ‘E’, ‘S’ represent a room with a rotating door facing north, west, east, and south respectively. The map is followed by
integers, the
th of which is equal to
for the
th door, counting the doors from the north-west corner in a row major order. You can assume that
(which is the number of rotating doors in the castle) is no more than 500, and the entrance (room at lower-left corner) and the room containing the secret door (room at upper-right corner) does not contain NeshimanGazes or rotating doors.
The Output
For each test case, your program should output a line containing a single integer which is the minimum amount of time required for Kianoosh to reach the secret door. In the case the secret door is not reachable with respect to the given map and rules, a line containing the phrase “Poor Kianoosh” should be printed.
Sample Input
1
3 3
.#.
..W
...
10
Sample Output
14
Amirkabir University of Technology - Local Contest - Round #2
题意:有一个迷宫,然后有些地方是不能通过的,有些地方是可以旋转的,旋转的房间只能从一个口进,然后通过旋转房间能够从另外的口出去。而不同的能够旋转的房间都对应有一个旋转90度所需要的时间。要你求出从迷宫的左下角到迷宫的右上角最少需要多少时间。
思路:不难想到,每个能旋转的房间其实最多只会进一次并出去一次,因为进去很多次其实不会有什么作用,只会浪费你的时间。那么这个其实是一个最短路问题,图是隐式的,我们用一个数组记录到达该房间要花费的最少时间。然后就是套Dijkstra的过程了。细节自己处理一下就行了。另外跑Dijkstra之前先跑一下bfs,看能不能到达终点。如果不能到达就直接输出无解,否则才跑Dijkstra。
代码:
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<stack>
#include<list>
#include<cstring>
#include<vector>
using namespace std;
#define LL long long
#define eps 1e-10
#define mp make_pair
#define MOD 10007
int n, m;
inline int row(int x) { return x / m; }
inline int col(int x) { return x%m; }
inline int getx(int r, int c) { return r*m + c; }
inline bool inRange(int r, int c) { return 0 <= r&&r < n && 0 <= c&&c < m; }
const int maxn = 100 + 5;
const int Move[2][4] = { { -1, 0, 1, 0 }, { 0, 1, 0, -1 } };
bool cango[4][260];
int T[4][260];
char map[maxn][maxn];
int h[maxn*maxn];
int g[maxn*maxn];
int cost[maxn*maxn];
struct State
{
char mz[maxn][maxn];
int g;
int h;
int x;
bool operator<(const State&st) const { return g + h>st.g + st.h; }
};
void CalH(int s)
{
queue<int> q;
q.push(s);
memset(h, -1, sizeof(h));
h[s] = 0;
while (q.size())
{
int x = q.front(); q.pop();
int r = row(x), c = col(x);
for (int i = 0; i < 4; ++i)
{
int rr = r + Move[0][i];
int cc = c + Move[1][i];
if (!inRange(rr, cc) || map[rr][cc] == '#') continue;
int y = getx(rr, cc);
if (h[y] != -1) continue;
h[y] = h[x] + 1;
q.push(y);
}
}
}
void input()
{
memset(cango, 0, sizeof(cango));
memset(T, 0, sizeof(T));
cango[0]['.'] = cango[1]['.'] = cango[2]['.'] = cango[3]['.'] = true;
cango[0]['S'] = cango[1]['W'] = cango[2]['N'] = cango[3]['E'] = true;
T[0]['W'] = 1; T[0]['N'] = 0; T[0]['E'] = 1; T[0]['S'] = 2;
T[1]['W'] = 2; T[1]['N'] = 1; T[1]['E'] = 0; T[1]['S'] = 1;
T[2]['W'] = 1; T[2]['N'] = 2; T[2]['E'] = 1; T[2]['S'] = 0;
T[3]['W'] = 0; T[3]['N'] = 1; T[3]['E'] = 2; T[3]['S'] = 1;
for (int i = 0; i < n; ++i) scanf("%s", map[i]);
CalH(getx(0, m - 1));
memset(cost, 0, sizeof(cost));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
if (map[i][j] != '.'&&map[i][j] != '#') scanf("%d", cost + getx(i, j));
}
bool reachable(int s)
{
queue<int> q;
q.push(s);
memset(g, -1, sizeof(g));
g[s] = 0;
while (q.size())
{
int x = q.front(); q.pop();
int r = row(x), c = col(x);
for (int i = 0; i < 4; ++i)
{
int rr = r + Move[0][i];
int cc = c + Move[1][i];
if (!inRange(rr, cc) || map[rr][cc] == '#' || g[getx(rr,cc)] != -1) continue;
if (!cango[i][map[rr][cc]]) continue;
int y = getx(rr, cc);
g[y] = g[x] + 1;
q.push(y);
}
}
return g[getx(0, m - 1)] != -1;
}
int Dijkstra(State &st)
{
memset(g, 0x3f, sizeof(g));
priority_queue<State> q;
q.push(st);
int x = st.x;
g[x] = 0;
while (q.size())
{
State temp = q.top(); q.pop();
x = temp.x;
int r = row(x), c = col(x);
if (x == getx(0, m - 1)) return g[x];
for (int i = 0; i < 4; ++i)
{
int rr = r + Move[0][i];
int cc = c + Move[1][i];
if (!inRange(rr, cc) || temp.mz[rr][cc] == '#') continue;
char ch = temp.mz[rr][cc];
if (!cango[i][ch]) continue;
ch = temp.mz[r][c];
int y = getx(rr, cc);
if (g[y] <= g[x] + 1 + cost[x] * T[i][ch]) continue;
State now = temp;
g[y] = g[x] + 1 + cost[x] * T[i][ch];
now.g = g[y];
now.h = h[y];
now.x = y;
q.push(now);
}
}
return -1;
}
void solve()
{
if (!reachable(getx(n - 1, 0))) {
printf("Poor Kianoosh\n");
return;
}
State start;
start.x = getx(n - 1, 0);
start.g = 0, start.h = h[getx(n - 1, 0)];
memcpy(start.mz, map, sizeof(start.mz));
int ans = Dijkstra(start);
if (ans == -1) printf("Poor Kianoosh\n");
else printf("%d\n", ans);
}
int main()
{
int T; cin >> T;
while (T--)
{
scanf("%d%d", &n, &m);
input();
solve();
}
}