UVa12080 Pesky Heroes
题目链接
本题是2005年 ACM ICPC 欧洲区域赛 西北 赛区 的 E 题。
题意
参见CSDN博主「overload1997」的原创文章,这里贴一下他写的题意:
有一个有n个关键点的洞窟的路线图,其中1为入口。
保证只有一个点与1相连,且每个点最多只跟三个点有连边,以及从每个点到1的路有且仅有一条。
洞窟中还有m个陷阱,位于m个关键点中。
英雄从入口走到了某个死胡同且一路上没有触发到任何陷阱,之后英雄在这个死胡同里安营扎寨。
我们的目的是协同恶法师将英雄找出来,为此需要找遍所有的【从入口到终点一路上没有陷阱】的死胡同。
但是我们所在的宫殿离洞窟太远了,并没有办法从入口进去,所以只能通过传送门派小兵过去找。
恶法师可以从某条道路上开启一个传送门,并将小兵们从远方的宫殿送往这条路上。
小兵一开始的行动方向为背离入口的方向,每次遇到一个岔路口必定选择左边的路走,遇到死胡同就掉头。
你可以令小兵在遇到某个岔路口时选择右边的路而不是左边的路,不同的小兵可以选择不同的岔口但是每只小兵最多只能右转一次。
当小兵走回传送门的时候就会被传送回去。
小兵遇到陷阱会死掉,所以你必须令小兵避开陷阱。
问找遍所有符合条件的死胡同所需要开的最少的传送门数。
还有一点是通过枚举题意推出来的:小兵所走过的路中不能有出来送小兵来的传送门之外的其他传送门
以及还有一点需要注意的是,对于小兵来说的左边并不是我们看地图的视角的左边,而是小兵自己在洞窟里的视角的左边。
博主「overload1997」的这个题意分析基本能懂,但“对于小兵来说的左边并不是我们看地图的视角的左边,而是小兵自己在洞窟里的视角的左边”这句还是有点懵,我又从原创力文档上找到了雅礼中学女神大佬陈丹琦的题解:
两相结合,这一点我就理解了,这里我再补上一张图方便读者理解:
从父节点前进视角,若左转将走向左子节点,若右转将走向右子节点;
从左子节点回退视角,若左转将走向右子节点,若右转将走向父节点;
从右子节点回退视角,若左转将走向父节点,若右转将走向左子节点。
分析
理解完题意后,就知道用树上的动态规划求解了。
博主「overload1997」的动态规划使用的状态是d[N][3]:d[i][0]表示节点u的父节点和i的道路上无兵通过时,访问找遍子树i所有符合条件的死胡同所需要开的最少的传送门数;d[i][1/2]表示节点i的父节点和u的道路上有兵通过(但没有右转过/已经右转过),访问找遍子树i所有符合条件的死胡同所需要开的最少的传送门数。这样的状态转移需要分类讨论,不一一细述。
陈丹琦的动态规划状态是:用trap[i]表示子树i是否有陷阱(节点i本身是陷阱或者i的子树有陷阱则子树i有陷阱),f[i]表示访问完i这个子树最少需要安排多少传送门,g[i]表示已经为节点i和其父节点的道路上安排了传送门,遍历完整个子树i另外最少还需要多少个传送门。女神大佬的这个动态规划状态转移就简洁很多了:f[i] = min(f[left_child] + f[right_child], 1+g[i])。若trap[left_child] && trap[right_child],则g[i] = +inf;否则g[i] = min(g[left_child] + g[right_child], g[left_child] + f[right_child], g[right_child] + f[left_child])。
AC代码
博主「overload1997」的动态规划:
#include <iostream>
using namespace std;#define N 50010
#define M 505
int d[N][3], g[N][3], c[N], n, m; bool trap[N];void dfs(int u, int fa = 0) {if (trap[u]) {d[u][0] = 0; d[u][1] = d[u][2] = N;} else if (c[u] == 1 && u > 1) {d[u][0] = 1; d[u][1] = d[u][2] = 0;} else if (c[u] == 2 || u == 1) {int s = u==1 ? g[u][0] : g[u][0]+g[u][1]-fa;dfs(s, u);d[u][0] = d[s][0]; d[u][1] = d[s][1]; d[u][2] = d[s][2];} else {int l = g[u][0]!=fa ? g[u][0] : g[u][1], r = g[u][0]+g[u][1]+g[u][2]-fa-l;dfs(l, u); dfs(r, u);d[u][2] = d[l][2] + d[r][2];d[u][1] = min(d[l][2] + min(d[r][0], d[r][1]), d[r][2] + min(d[l][0], d[l][1]));d[u][0] = min(d[l][0] + d[r][0], 1 + d[u][1]);}
}int solve() {for (int u=1; u<=n; ++u) {cin >> c[u]; trap[u] = false;for (int i=0; i<c[u]; ++i) cin >> g[u][i];}while (m--) {int u; cin >> u; trap[u] = true;}dfs(1);return d[1][0];
}int main() {ios::sync_with_stdio(false);while (cin>>n>>m && n) cout << solve() << endl;return 0;
}
陈丹琦的动态规划:
#include <iostream>
using namespace std;#define N 50010
#define M 505
int t[N][3], f[N], g[N], c[N], n, m; bool trap[N];bool dfs(int u, int fa = 0) {if (trap[u]) {f[u] = g[u] = 0;} else if (c[u] == 1 && u > 1) {f[u] = 1; g[u] = 0;} else if (c[u] == 2 || u == 1) {int s = u==1 ? t[u][0] : t[u][0]+t[u][1]-fa;if (dfs(s, u)) trap[u] = true;f[u] = f[s]; g[u] = g[s];} else {int l = t[u][0]!=fa ? t[u][0] : t[u][1], r = t[u][0]+t[u][1]+t[u][2]-fa-l;if (dfs(l, u)) trap[u] = true;if (dfs(r, u)) trap[u] = true;g[u] = trap[l] && trap[r] ? N : min(g[l] + g[r], min(g[l] + f[r], g[r] + f[l]));f[u] = min(f[l]+f[r], g[u]+1);}return trap[u];
}int solve() {for (int u=1; u<=n; ++u) {cin >> c[u]; trap[u] = false;for (int i=0; i<c[u]; ++i) cin >> t[u][i];}while (m--) {int u; cin >> u; trap[u] = true;}dfs(1);return f[1];
}int main() {ios::sync_with_stdio(false);while (cin>>n>>m && n) cout << solve() << endl;return 0;
}
UVa12080 Pesky Heroes相关推荐
- 杭电oj题目题型分类(转)
1001 整数求和 水题 1002 C语言实验题--两个数比较 水题 1003 1.2.3.4.5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 ...
- HDOJ题目分类大全
版权声明:本文为博主原创文章,欢迎转载,转载请注明本文链接! https://blog.csdn.net/qq_38238041/article/details/78178043 杭电里面有很多题目, ...
- HDU题目分类大全【大集合】
基础题: 1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056.105 ...
- 《算法竞赛入门经典——训练指南》第一章相关内容
#<算法竞赛入门经典--训练指南>第一章相关内容 希望各位大牛能指导! 红色为已经做了的...黄色背景是还有不懂地方,希望在年前能刷完第一章啊.... 更新版.google上貌似又加了ex ...
- 杭电OJ题目分类(转载)
1001 整数求和 水题 1002 C语言实验题--两个数比较 水题 1003 1.2.3.4.5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 ...
- hdoj杭电问题分类
杭电上的题虽然多,但是一直苦于找不到问题分类,网页都是英文的,所以平时做题也没怎么看,今天仔细一看,问题分类竟然就在主页....做了那么久的题居然没发现,表示已经狗带..不要笑,不知道有没有像我一样傻 ...
- 转载:Hdu 题目分类
原址点击 基础题:1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056. ...
- HD OJ 题目分类
动态规划:2037 2054 2084 hdu题目分类(转) http://blog.csdn.net/vsooda/article/details/7258791 1001 整数求和 水题 1002 ...
- hdu与poj题目分类
POJ 初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(po ...
- hdu HDOJ 题目分类(转)
动态规划:2037 2054 2084 hdu题目分类(转) http://apps.hi.baidu.com/share/detail/17053154 1001 整数求和 水题 1002 C语言实 ...
最新文章
- php解析api xml并输出到html页面,怎样操作JS读取xml内容并输出到div内
- 移植Linux3.4.2版本内核到mini2440
- Java案例:编译器生成桥方法
- linux定时重启命令
- c语言斐波那契数列递归数组,C语言数据结构学习:递归之斐波那契数列
- 如何看一份DBC文件
- pycharm中实现sin和cos函数曲线图
- C#实现所有CRC8,CRC16,CRC32校验算法
- 单例模式--懒汉模式和饿汉模式
- PCF8591使用及Python控制
- leet-code Z 字形变换详解
- 机器学习系列-- 异常检测(Anomaly Detection)
- 被国人误传了数千年的七句话(转自天涯)
- 【二胡音乐】陈军《胡弓传奇》
- 2012年中国各省市区GDP排行榜 附各主要城市GDP排行榜
- 基于STM8的数字温度计设计
- DICOM 图像传输:使用 LeadTools 实现 C-Store SCP 服务
- Shell编程实战范例
- 使用Python提取txt文件中的数据到excel中
- iOS刷机后安装源和插件
热门文章
- PAT-B 1055. 集体照
- 你知道期权和期货有什么关联和区别吗?解析一下!
- 自己出的中考模拟卷(数学)
- 【学习】Cognos超详细中文教程
- 帝国cms漏洞分析前台XSS漏洞
- C# 操作Active Directory (AD)的操作类
- 【数据库查询--电影制片系列】--检索出StarsIn表中在1990年拍摄过电影的所有影星,或者拍摄过电影名中含有3的电影的所有影星。
- redis数据库使用02、python 操作 || redis主从模式
- 【CSDN实训】面向对象编程的概念及应用方法
- layer弹出层php,layer官方演示与讲解(jQuery弹出层插件)