题目链接

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. 20155318 2016-2017-2 《Java程序设计》第二周学习总结

    20155318 2016-2017-2 <Java程序设计>第二周学习总结 教材学习内容总结 Java编程风格 基本语法与C相似:调用main函数写public static void ...

  2. javaWeb项目-文件下载的消息头和编码问题

    一.问题: 做web项目经常提到的一个需求就是页面的文件下载,那么下载的时候在后台为什么要设置响应消息头?为什么这样设置? 二.解决: 1.例子 //设置响应的消息头response.setConte ...

  3. 优步UBER司机奖励政策:含高峰、翻倍、行程、金牌司机、保底奖励(持续更新...)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://didi-uber.com/archiv ...

  4. 二、Web框架实现

    一.简单web(socket) 在前一篇WEB框架概述一文中已经详细了解了:从浏览器键入一个URL到返回HTML内容的整个过程.说到底,本质上其实就是一个socket服务端,用户的浏览器其实就是一个s ...

  5. 深入解析QML引擎, 第1部分:QML文件加载

    译者注:这个解析QML引擎的文章共4篇,分析非常透彻,在国内几乎没有找到类似的分析,为了便于国内的QT/QML爱好者和工作者也能更好的学习和理解QML引擎,故将这个系列的4篇文章翻译过来.翻译并不是完 ...

  6. python-模块详解

    模块: 模块的分类: 第三方模块/扩展模块:没在安装python解释器的时候安装的那些功能 自定义模块:你写的功能如果是一个通用的功能,那你就把它当做一个模块 内置模块:安装python解释器的时候跟 ...

  7. Keil出错解决方法

    1.安装KEIL5后创建工程后出现这个报错 解决方法:打开下图目录的文件. Keil.STM32F1xx_DFP.pdsc文件是只读文件,必须将只读属性取消. 如下图所示,注释掉红色圆圈的哪一行,保存 ...

  8. CMDBuild2.4.3安装配置

    参考文档: 官网:http://www.cmdbuild.org/en 参考:http://blog.csdn.net/shawn210/article/details/70230248 本文涉及CM ...

  9. 启动sshd时,报“Could not load host key”错

    原文发表于cu:2016-05-24 现象:启动sshd服务时,虽看似服务启动成功,但客户端并不能连接上sshd服务器端.如下: [root@aefe8007a17d ~]# /usr/sbin/ss ...

  10. Hackerank-Array-NewYearChaos

    题目背景描述 新年第一天,N 个人排队坐过山车.每个人穿有带编号的衣服 \([1, 2, 3, ...]\). 因为排队时间太久,有人发现给前面相邻的人喂一颗糖,就可以和他交换位置,而每人手里只有两颗 ...