题目链接

本题是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相关推荐

  1. 杭电oj题目题型分类(转)

    1001 整数求和 水题 1002 C语言实验题--两个数比较 水题 1003 1.2.3.4.5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 ...

  2. HDOJ题目分类大全

    版权声明:本文为博主原创文章,欢迎转载,转载请注明本文链接! https://blog.csdn.net/qq_38238041/article/details/78178043 杭电里面有很多题目, ...

  3. HDU题目分类大全【大集合】

    基础题: 1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029.  1032.1037.1040.1048.1056.105 ...

  4. 《算法竞赛入门经典——训练指南》第一章相关内容

    #<算法竞赛入门经典--训练指南>第一章相关内容 希望各位大牛能指导! 红色为已经做了的...黄色背景是还有不懂地方,希望在年前能刷完第一章啊.... 更新版.google上貌似又加了ex ...

  5. 杭电OJ题目分类(转载)

    1001 整数求和 水题 1002 C语言实验题--两个数比较 水题 1003 1.2.3.4.5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 ...

  6. hdoj杭电问题分类

    杭电上的题虽然多,但是一直苦于找不到问题分类,网页都是英文的,所以平时做题也没怎么看,今天仔细一看,问题分类竟然就在主页....做了那么久的题居然没发现,表示已经狗带..不要笑,不知道有没有像我一样傻 ...

  7. 转载:Hdu 题目分类

    原址点击 基础题:1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056. ...

  8. HD OJ 题目分类

    动态规划:2037 2054 2084 hdu题目分类(转) http://blog.csdn.net/vsooda/article/details/7258791 1001 整数求和 水题 1002 ...

  9. hdu与poj题目分类

    POJ 初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(po ...

  10. hdu HDOJ 题目分类(转)

    动态规划:2037 2054 2084 hdu题目分类(转) http://apps.hi.baidu.com/share/detail/17053154 1001 整数求和 水题 1002 C语言实 ...

最新文章

  1. php解析api xml并输出到html页面,怎样操作JS读取xml内容并输出到div内
  2. 移植Linux3.4.2版本内核到mini2440
  3. Java案例:编译器生成桥方法
  4. linux定时重启命令
  5. c语言斐波那契数列递归数组,C语言数据结构学习:递归之斐波那契数列
  6. 如何看一份DBC文件
  7. pycharm中实现sin和cos函数曲线图
  8. C#实现所有CRC8,CRC16,CRC32校验算法
  9. 单例模式--懒汉模式和饿汉模式
  10. PCF8591使用及Python控制
  11. leet-code Z 字形变换详解
  12. 机器学习系列-- 异常检测(Anomaly Detection)
  13. 被国人误传了数千年的七句话(转自天涯)
  14. 【二胡音乐】陈军《胡弓传奇》
  15. 2012年中国各省市区GDP排行榜 附各主要城市GDP排行榜
  16. 基于STM8的数字温度计设计
  17. DICOM 图像传输:使用 LeadTools 实现 C-Store SCP 服务
  18. Shell编程实战范例
  19. 使用Python提取txt文件中的数据到excel中
  20. iOS刷机后安装源和插件

热门文章

  1. PAT-B 1055. 集体照
  2. 你知道期权和期货有什么关联和区别吗?解析一下!
  3. 自己出的中考模拟卷(数学)
  4. 【学习】Cognos超详细中文教程
  5. 帝国cms漏洞分析前台XSS漏洞
  6. C# 操作Active Directory (AD)的操作类
  7. 【数据库查询--电影制片系列】--检索出StarsIn表中在1990年拍摄过电影的所有影星,或者拍摄过电影名中含有3的电影的所有影星。
  8. redis数据库使用02、python 操作 || redis主从模式
  9. 【CSDN实训】面向对象编程的概念及应用方法
  10. layer弹出层php,layer官方演示与讲解(jQuery弹出层插件)