题目链接

Problem Description
《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.

Input
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.

Output
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
Sample Input
2 2
S#
#T
2 5
SB###
##P#T
4 7
SP.....
P#.....
......#
B...##T
0 0
Sample Output
-1
8
11
题意
给一个100x100的迷宫,'.'表示路面,'S'表示起点,'T'表示终点;'#'表示毒气区,进入毒气区必须要消耗一个氧气;'B'表示氧气区,每次进入自动获得一个氧气,可反复进入从而获得多个,但最多携带5个;'P'表示加速药,获得原理和氧气一样,使用后使下一次移动不耗时,可以无限携带。一次移动可以移动到相邻的四个格子,花费一个单位时间,如果移动到了毒气区,将在毒气区额外停留一个单位时间。求从S到T的最短时间,如果不能到达,输出-1。
分析
加速药拿到立刻用掉和留着后面用的效果是一样的,所以完全不必考虑加速药的存在。
氧气数量是这道题的关键,所以把状态定义为(x, y, n),表示在(x,y)时还有n个氧气,当氧气用完时,就不能向毒气区转移了;同时我们还希望求出的最短时间,所以dp[x][y][n]=t,表示从起点出发到达状态(x, y, n)花费的最少时间,这样以后,如果终点是(tx,ty),那么只要dp[tx][ty][i],(i=0,1,2,3,4,5)中任何一个不是无穷大,就是可以到达终点的。
接下来是状态之间的转移:
(x, y, n)可以向四个方向转移,假设下一个地方是(tx,ty),那么:
(tx,ty)是'.'或'S',就用dp[x][y][n]+1更新dp[tx][ty][n];
(tx,ty)是'T',同样用dp[x][y][n]+1更新dp[tx][ty][n],并且不再向下转移;
(tx,ty)是'B',氧气数量增加,如果n<5,那么还可以拿氧气,用dp[x][y][n]+1更新dp[tx][ty][n+1],否则更新dp[tx][ty][n];
(tx,ty)是'P',下一步不耗时,用dp[x][y][n]更新dp[tx][ty][n];
(tx,ty)是'#',氧气数量减少,只有当n>0时,才可以进毒气区,因为要额外花费一个单位时间,用dp[x][y][n]+2更新dp[tx][ty][n-1]。
那么所有的转移都搞定了,初始状态很简单,假设起点是(sx,sy),那么就是dp[sx][sy][0]=0,其他所有的状态都是INF。只要把所有可能到达的状态更新了,那么答案就在dp[tx][ty][i]中取最小就行了。
需要注意的是,状态的更新需要用类似于BFS的顺序,不断的用已知的最优状态,去更新相邻的未知状态,直至遍历完所有的状态,复杂度为O(5nm)。
总结
网格题真的是一点想法也没有,看数据量也不大,就试着写了个状态推一推,没想到真的推出来了。经大佬指点用spfa也可以搞,等学会了再补题把。
代码
#include<stdio.h>
#include<memory.h>
#include<queue>
using std::queue;
char g[][];
int dp[][][];//从起点出发直到在(x,y)拿着n个氧气罐所需最少时间
#define INF 1000000
int nx[] = { -,,, };
int ny[] = { ,,,- };
struct state
{
int x, y, n;
state(int _i=,int _j=,int _x=):x(_i),y(_j),n(_x){}
}; int main()
{
int n, m;
int sx=, sy=, ex=, ey=;
while(EOF!=scanf("%d %d",&n,&m)&&n&&m){
for(int i=;i<=n;++i){
scanf("%s", g[i] + );
g[i][] = '$';
for(int j=;j<=m;++j){
if (g[i][j] == 'S') { sx = i; sy = j; }
else if (g[i][j] == 'T') { ex = i; ey = j; }
//输入时顺带初始化dp数组
for (int t = ; t <= ; ++t)dp[i][j][t] = INF;
}
}
//起始状态
dp[sx][sy][] = ;
//bfs的顺序更新
queue<state> mq;
mq.push(state(sx, sy, ));
state cur;
int tx, ty;
while(!mq.empty()) {
cur = mq.front(); mq.pop();
for(int k=;k<;++k)//四个转移方向
{
tx = cur.x + nx[k];
ty = cur.y + ny[k];
//不在地图内
if (tx< || tx>n || ty< || ty>m)continue; switch(g[tx][ty]){
case 'S':
case '.':
if (dp[tx][ty][cur.n] > dp[cur.x][cur.y][cur.n] + ){
dp[tx][ty][cur.n] = dp[cur.x][cur.y][cur.n] + ;
mq.push(state(tx, ty, cur.n));
}
break;
case 'T':
//不再向下转移
if (dp[tx][ty][cur.n] > dp[cur.x][cur.y][cur.n] + )
dp[tx][ty][cur.n] = dp[cur.x][cur.y][cur.n] + ;
break;
case 'P':
if (dp[tx][ty][cur.n] > dp[cur.x][cur.y][cur.n]){
dp[tx][ty][cur.n] = dp[cur.x][cur.y][cur.n];
mq.push(state(tx, ty, cur.n));
}
break;
case 'B':
if (cur.n<&&dp[tx][ty][cur.n + ] > dp[cur.x][cur.y][cur.n] + ){
dp[tx][ty][cur.n + ] = dp[cur.x][cur.y][cur.n] + ;
mq.push(state(tx, ty, cur.n +));
}
else if(cur.n==&&dp[tx][ty][cur.n] > dp[cur.x][cur.y][cur.n] + ){
dp[tx][ty][cur.n] = dp[cur.x][cur.y][cur.n] + ;
mq.push(state(tx, ty, cur.n));
}
break;
case '#':
if (cur.n>&&dp[tx][ty][cur.n - ] > dp[cur.x][cur.y][cur.n] + ){
dp[tx][ty][cur.n - ] = dp[cur.x][cur.y][cur.n] + ;
mq.push(state(tx, ty, cur.n -));
}
break;
default:
break;
} }
}
int ans = INF;
for(int i=;i<=;++i){
if (ans > dp[ex][ey][i])ans = dp[ex][ey][i];
}
if (ans >= INF)printf("-1\n");
else printf("%d\n", ans);
}
}

hihocoder 1828 Saving Tang Monk II (DP+BFS)的更多相关文章

  1. 北京2018网络赛 hihocoder#1828 : Saving Tang Monk II (BFS + DP +多开一维)

    hihocoder 1828 :https://hihocoder.com/problemset/problem/1828 学习参考:https://www.cnblogs.com/tobyw/p/9 ...

  2. hihocoder #1828 : Saving Tang Monk II(BFS)

    描述 <Journey to the West>(also <Monkey>) is one of the Four Great Classical Novels of Chi ...

  3. ACM-ICPC2018北京网络赛 Saving Tang Monk II(bfs+优先队列)

    题目1 : Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 <Journey to the West>(also < ...

  4. ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 A、Saving Tang Monk II 【状态搜索】

    任意门:http://hihocoder.com/problemset/problem/1828 Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制:25 ...

  5. Saving Tang Monk II(bfs+优先队列)

    Saving Tang Monk II https://hihocoder.com/problemset/problem/1828 时间限制:1000ms 单点时限:1000ms 内存限制:256MB ...

  6. Saving Tang Monk II HihoCoder - 1828 2018北京赛站网络赛A题

    <Journey to the West>(also <Monkey>) is one of the Four Great Classical Novels of Chines ...

  7. hihoCoder-1828 2018亚洲区预选赛北京赛站网络赛 A.Saving Tang Monk II BFS

    题面 题意:N*M的网格图里,有起点S,终点T,然后有'.'表示一般房间,'#'表示毒气房间,进入毒气房间要消耗一个氧气瓶,而且要多停留一分钟,'B'表示放氧气瓶的房间,每次进入可以获得一个氧气瓶,最 ...

  8. Saving Tang Monk II

    题目链接:http://hihocoder.com/contest/acmicpc2018beijingonline/problem/1 AC代码: #include<bits/stdc++.h ...

  9. ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 A.Saving Tang Monk II(优先队列广搜)

    #include<bits/stdc++.h> using namespace std; ; ; char G[maxN][maxN]; ]; int n, m, sx, sy, ex, ...

随机推荐

  1. # 2017-2018-1 20155232《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155232<信息安全技术>实验二--Windows口令破解 [实验目的] 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 ...

  2. 20155316 实验一《Java开发环境的熟悉》实验报告

    一.命令行下Java程序的开发 按照老师提供的步骤,运行程序如下: 二.IDEA下Java程序开发.调试 设置条件断点如下: 三.练习题 实现四则运算,并进行测试 实现效果:实现任意两个整数的加减乘除 ...

  3. Kali linux更新源

    1.更新软件源: 修改sources.list文件: leafpad /etc/apt/sources.list 然后选择添加以下适合自己较快的源(可自由选择,不一定要全部): #官方源deb htt ...

  4. WPF RoutedEvent and HitTest - 简书

    原文:WPF RoutedEvent and HitTest - 简书 学习的时候切忌心浮气躁,慢慢的过每一个知识点,不要漏掉任何细节.不然当遇到细节问题的时候,会恼,会闹,会悔不该当初--花一下午调 ...

  5. [BZOJ2738]矩阵乘法-[整体二分+树状数组]

    Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. (N<=500,Q<=60000) Solution 考虑二分答案,问题转化为求矩阵内为1 ...

  6. 【转载】DXUT进阶

    原文:DXUT进阶 概要 这个指南涵盖了更多DXUT的高级应用. 这个指南里的大部分功能是可选的, 为了以最小的代价来增强你的应用程序. DXUT提供了一个简单的基于GUI系统的精灵和一个设备设置对话 ...

  7. day 4 名片管理系统 -函数版

    修改没有用函数的程序 具有独立功能的代码块 源程序 #1.打印功能信息 print("*"*50) print("\t名片管理系统 V3\t") print(& ...

  8. appium+python自动化☞appium python api大全

    整理了一些常用的appium python api,供学习使用...

  9. [C++]boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

  10. [kuangbin带你飞]专题一 简单搜索 回顾总结

    第二题:bfs,忘了将queue清空. 第三题:bfs,记得使用vis数组,防止重复入队