(intermediate) UVA 最短路 10967 The Great Escape

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();
	}
}


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值