题目1 : Saving Tang Monk II
时间限制:1000ms
单点时限:1000ms
内存限制:256MB
描述
《Journey to the West》(also 《Monkey》) is one of the Four Great Classical Novels of Chinese literature. It was written by Wu Cheng'en during the Ming Dynasty. In this novel, Monkey King Sun Wukong, pig Zhu Bajie and Sha Wujing, escorted Tang Monk to India to get sacred Buddhism texts.
During the journey, Tang Monk was often captured by demons. Most of demons wanted to eat Tang Monk to achieve immortality, but some female demons just wanted to marry him because he was handsome. So, fighting demons and saving Monk Tang is the major job for Sun Wukong to do.
Once, Tang Monk was captured by the demon White Bones. White Bones lived in a palace and she cuffed Tang Monk in a room. Sun Wukong managed to get into the palace, and he wanted to reach Tang Monk and rescue him.
The palace can be described as a matrix of characters. Different characters stand for different rooms as below:
'S' : The original position of Sun Wukong
'T' : The location of Tang Monk
'.' : An empty room
'#' : A deadly gas room.
'B' : A room with unlimited number of oxygen bottles. Every time Sun Wukong entered a 'B' room from other rooms, he would get an oxygen bottle. But staying there would not get Sun Wukong more oxygen bottles. Sun Wukong could carry at most 5 oxygen bottles at the same time.
'P' : A room with unlimited number of speed-up pills. Every time Sun Wukong entered a 'P' room from other rooms, he would get a speed-up pill. But staying there would not get Sun Wukong more speed-up pills. Sun Wukong could bring unlimited number of speed-up pills with him.
Sun Wukong could move in the palace. For each move, Sun Wukong might go to the adjacent rooms in 4 directions(north, west,south and east). But Sun Wukong couldn't get into a '#' room(deadly gas room) without an oxygen bottle. Entering a '#' room each time would cost Sun Wukong one oxygen bottle.
Each move took Sun Wukong one minute. But if Sun Wukong ate a speed-up pill, he could make next move without spending any time. In other words, each speed-up pill could save Sun Wukong one minute. And if Sun Wukong went into a '#' room, he had to stay there for one extra minute to recover his health.
Since Sun Wukong was an impatient monkey, he wanted to save Tang Monk as soon as possible. Please figure out the minimum time Sun Wukong needed to reach Tang Monk.
输入
There are no more than 25 test cases.
For each case, the first line includes two integers N and M(0 < N,M ≤ 100), meaning that the palace is a N × M matrix.
Then the N×M matrix follows.
The input ends with N = 0 and M = 0.
输出
For each test case, print the minimum time (in minute) Sun Wukong needed to save Tang Monk. If it's impossible for Sun Wukong to complete the mission, print -1
样例输入
2 2 S# #T 2 5 SB### ##P#T 4 7 SP..... P#..... ......# B...##T 0 0
样例输出
-1 8 11
一、题目地址
二、大致题意
给出一个N*M的矩阵。内部元素的含义为:
'S':孙悟空的起点
'T':唐僧的位置
'.' :一个空房间
'#':一个致命的毒气室。
'B':一个无限数量氧气瓶的房间。 每次孙悟空从其他房间进入'B'房间时,他都会得到一个氧气瓶。 但留在那里不会让孙悟空更多的氧气瓶。 孙悟空最多可同时携带5个氧气瓶。
'P':一个无限量加速药丸的房间。 孙悟空每次从其他房间进入'P'房间,他都会得到加速药丸。 但留在那里不会让孙悟空更加加速。 孙悟空可以携带无限数量的加速药片。
每一步都让孙悟空一分钟。 但如果孙悟空吃了加速药,他可以不花任何时间做下一步行动。 换句话说,每个加速药丸可以拯救孙悟空一分钟。 如果孙悟空进入'#'房间,他必须再待一分钟才能恢复健康。
询问的是拯救唐僧所需的最短时间。
三、大致思路
一道很明显的搜索题,原本以为复杂度会跑不出来可能需要剪枝,最后发现竟然不需要。
首先需要明确的一点是,当孙悟空走到一个加速药的房间时,他是一定会拿走加速药的,因为不拿白不拿。然后拿到这个加速药后,他必定是会在下一秒选择吃掉,因为虽然可以无限的携带这种加速药,但是药吃的先后顺序是不会影响到达终点的时间的。但是如果不马上吃掉加速药,反而可能导致最后的时间延长。这一点一定要先脑补出来。
接着就是记录状态的问题。
开一个四维的数组dis[x ][y ][z ][p ].前面的两个维度用以记录到达了(x,y)的位置,第三个维度用以记录到达了(x,y)位置时孙悟空身上携带的氧气瓶的数量,第四个维度用以记录在(x,y)位置上拥有z个氧气瓶时是否拥有加速药。那么这个dis就可以用以更新孙悟空到达了(x,y)这个位置拥有z个氧气瓶,且有P个加速药情况下的最小时间。然后搜就完事了,竟然不需要剪枝,很神奇。
四、代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<functional>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long LL;
int gcd(int a, int b) { return a == 0 ? b : gcd(b % a, a); }
int n, m;
char mmp[105][105];
int sx, sy, ex, ey;
int dis[105][105][7][2];
int x[] = { 1,-1,0,0 };
int y[] = { 0,0,1,-1 };
struct Node
{
int x, y;
int step, B, P;
};
void read()
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%c", &mmp[i][j]);
if (mmp[i][j] == 'S')
{
sx = i, sy = j;
}
else if (mmp[i][j] == 'T')
{
ex = i, ey = j;
}
}
getchar();
}
}
void BFS()
{
int ans = inf;
memset(dis, inf, sizeof(dis));
dis[sx][sy][0][0] = 0;
queue<Node>q;
Node st;
st.B = 0, st.P = 0, st.step = 0; st.x = sx, st.y = sy;
q.push(st);
while (!q.empty())
{
Node t = q.front();
//printf("%d %d %d\n", t.x, t.y,t.step);
q.pop();
for (int i = 0; i < 4; i++)
{
int xx = t.x + x[i], yy = t.y + y[i];
if (xx >= 1 && xx <= n&&yy >= 1 && yy <= m)
{
if (mmp[xx][yy] == '#')
{
if (t.B != 0)
{
Node nx;
nx.x = xx, nx.y = yy;
nx.B = t.B - 1;
if (t.P > 0) {
nx.P = t.P - 1;
nx.step = t.step + 1;
}
else {
nx.P = t.P;
nx.step = t.step + 2;
}
if (dis[nx.x][nx.y][nx.B][nx.P] > nx.step)
{
q.push(nx);
dis[nx.x][nx.y][nx.B][nx.P] = nx.step;
}
}
}
else if (mmp[xx][yy] == 'B')
{
Node nx;
nx.x = xx, nx.y = yy;
if (t.B == 5)
nx.B = t.B;
else
nx.B = t.B + 1;
if (t.P > 0)
{
nx.P = t.P - 1; nx.step = t.step;
}
else
{
nx.P = t.P; nx.step = t.step + 1;
}
if (dis[nx.x][nx.y][nx.B][nx.P] > nx.step)
{
q.push(nx);
dis[nx.x][nx.y][nx.B][nx.P] = nx.step;
}
}
else if (mmp[xx][yy] == 'P')
{
Node nx;
nx.x = xx, nx.y = yy, nx.B = t.B;
if (t.P > 0)
{
nx.P = t.P; nx.step = t.step;
}
else
{
nx.P = t.P + 1; nx.step = t.step + 1;
}
if (dis[nx.x][nx.y][nx.B][nx.P] > nx.step)
{
q.push(nx);
dis[nx.x][nx.y][nx.B][nx.P] = nx.step;
}
}
else if (mmp[xx][yy] == 'T')
{
if (t.P > 0)ans = min(ans, t.step);
else ans = min(ans, t.step + 1);
}
else
{
Node nx;
nx.x = xx, nx.y = yy, nx.B = t.B;
if (t.P > 0)
{
nx.P = t.P - 1; nx.step = t.step;
}
else
{
nx.P = t.P; nx.step = t.step + 1;
}
if (dis[nx.x][nx.y][nx.B][nx.P] > nx.step)
{
q.push(nx);
dis[nx.x][nx.y][nx.B][nx.P] = nx.step;
}
}
}
}
}
if (ans == inf)printf("-1\n");
else printf("%d\n", ans);
}
int main()
{
while (scanf("%d %d", &n, &m), n && m)
{
getchar();
read();
BFS();
}
}