hihocoder 1828 Saving Tang Monk II (DP+BFS)
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.
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.
S#
#T
2 5
SB###
##P#T
4 7
SP.....
P#.....
......#
B...##T
0 0
8
11
氧气数量是这道题的关键,所以把状态定义为(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)。
#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)的更多相关文章
- 北京2018网络赛 hihocoder#1828 : Saving Tang Monk II (BFS + DP +多开一维)
hihocoder 1828 :https://hihocoder.com/problemset/problem/1828 学习参考:https://www.cnblogs.com/tobyw/p/9 ...
- hihocoder #1828 : Saving Tang Monk II(BFS)
描述 <Journey to the West>(also <Monkey>) is one of the Four Great Classical Novels of Chi ...
- ACM-ICPC2018北京网络赛 Saving Tang Monk II(bfs+优先队列)
题目1 : Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 <Journey to the West>(also < ...
- ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 A、Saving Tang Monk II 【状态搜索】
任意门:http://hihocoder.com/problemset/problem/1828 Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制:25 ...
- Saving Tang Monk II(bfs+优先队列)
Saving Tang Monk II https://hihocoder.com/problemset/problem/1828 时间限制:1000ms 单点时限:1000ms 内存限制:256MB ...
- Saving Tang Monk II HihoCoder - 1828 2018北京赛站网络赛A题
<Journey to the West>(also <Monkey>) is one of the Four Great Classical Novels of Chines ...
- hihoCoder-1828 2018亚洲区预选赛北京赛站网络赛 A.Saving Tang Monk II BFS
题面 题意:N*M的网格图里,有起点S,终点T,然后有'.'表示一般房间,'#'表示毒气房间,进入毒气房间要消耗一个氧气瓶,而且要多停留一分钟,'B'表示放氧气瓶的房间,每次进入可以获得一个氧气瓶,最 ...
- Saving Tang Monk II
题目链接:http://hihocoder.com/contest/acmicpc2018beijingonline/problem/1 AC代码: #include<bits/stdc++.h ...
- 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, ...
随机推荐
- 20155305乔磊2016-2017-2《Java程序设计》第三周学习总结
20155305乔磊 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 对象(Object):存在的具体实体,具有明确的状态和行为 类(Class):具有相同属 ...
- 20155320信息安全系统设计第二周课堂考试总结及myod的实现
20155320 信息安全系统设计第二周课堂考试总结及myod的实现 第二周测试一二已在课上提交 第二周测试3-gdb测试 用gcc -g编译vi输入的代码 在main函数中设置一个行断点 在main ...
- Why HBase
3.1.1,为什么选用HBases a) 容量巨大 HBase 的单表可以有百亿行.百万列,数据矩阵横向和纵向两个维度所支持的数据量级 都非常具有弹性.传统的关系型数据库,如 Oracle ...
- 创龙OMAPL138的SPI FLASH读写
1. 目前最大的疑问是OMAPL138和DSP6748的DSP部分是完全一样的吗(虽然知道芯片完全是引脚兼容的)?因此现在使用OMAPL138的DSP内核去读写一下外部的SPI FLASH芯片,先看下 ...
- 【jQuery学习】用JavaScript写一个输出多选框的个数报错:Cannot set property 'onclick' of null"
说明:代码段来源于:<锋利的jQuery> 根据代码段我补充的代码如下: <!DOCTYPE html> <html> <head> <meta ...
- C#反射的简单示例
反射(Reflection)可以在运行时获 得.NET中每一个类型(包括类.结构.委托.接口和枚举等)的成员,包括方法.属性.事件,以及构造函数等.还可以获得每个成员的名称.限定符和参数等反正说白了就 ...
- 33.[LeetCode] Search in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- Python数据挖掘——数据预处理
Python数据挖掘——数据预处理 数据预处理 数据质量 准确性.完整性.一致性.时效性.可信性.可解释性 数据预处理的主要任务 数据清理 数据集成 数据归约 维归约 数值归约 数据变换 规范化 数据 ...
- 浅谈TSM概念、系统架构及技术发展
NFC作为一种近距离的无线通信技术,提供了一种更直接.更安全的现场交互解决方案.它能够允许电子设备之间进行非接触式点对点数据传输,实现数据交换.访问内容与服务.有了它,手机不再只是打电话.发短信以及上 ...
- C++:this指针的简单理解
一.什么是this指针 要想理解什么是this指针,首先必须理解在C++中是如何为类的对象分配内存空间的. #include<iostream> using namespace std; ...