hihocoder #1055 : 刷油漆(树形dp)
当一个节点被选择后,它的所有祖先节点也要被选择
该条件换一个说法,可以解释为:只有当选择了一个节点后,我们才可以选择它的子节点。
我们首先建立状态f[i][k]
,f[i][k]
表示以i
节点为根的子树,在满足条件一的情况下,选择至多k
的节点能够得到的最大权值。
则可以写出状态转移情况:
- 选择i节点:
f[i][k]
等于w[i]
加上所有子节点选择k-1
个节点的最大权值 - 不选择i节点:
f[i][k] = 0
不选择i节点很好处理,那么我们如何处理选择i节点时,子节点的情况?
根据题目描述,我们知道给定的节点i
可能有多个儿子节点,不妨假设其有m
个儿子节点。
则可以表示为,在m
个儿子上一共选择k-1
个节点,使得选择的节点权值之和最大。
举个例子,比如样例:
我们在计算f[1][4]
时,需要考虑对于以2,3,4分别为根节点子树,一共选择3个节点,来使得权值最大。也就是说在2子树中选择x
个节点,3子树中选择y
个节点,4子树中选择z
个节点,使得x+y+z=3
。
很显然,该问题同样是一个动态规划问题:
建立状态g[i][j]
,g[i][j]
表示前i个儿子选择j个节点时最大权值,则有状态转移过程:
g[i][j] = max{g[i - 1][j - k] + f[childId][k] | k = 0 .. j}
时间限制:10000ms
-
描述
上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不同的数字,并且这些数字都是处于1..N的范围之内,每根木棍都连接着两个不同的小球,并且保证任意两个小球间都不存在两条不同的路径可以互相到达。没错,这次说的还是这棵树玩具的故事!
小Ho的树玩具的质量似乎不是很好,短短玩了几个星期,便掉漆了!
“简直是一场噩梦!”小Ho拿着树玩具眼含热泪道。
“这有什么好忧伤的,自己买点油漆刷一刷不就行了?”小Hi表示不能理解。
“还可以这样?”小Ho顿时兴高采烈了起来,立马跑出去买回来了油漆,但是小Ho身上的钱却不够——于是他只买回了有限的油漆,这些油漆最多能给M个结点涂上颜色,这就意味着小Ho不能够将他心爱的树玩具中的每一个结点都涂上油漆!
小Ho低头思索了半天——他既不想只选一部分结点补漆,也不想找小Hi借钱,但是很快,他想出了一个非常棒的主意:将包含1号结点的一部分连通的结点进行涂漆(这里的连通指的是这一些涂漆的结点可以互相到达并且不会经过没有涂漆的结点),然后将剩下的结点拆掉!
那么究竟选择哪些结点进行涂漆呢?小Ho想了想给每个结点都评上了分——他希望最后留下来,也就是涂漆了的那些结点的评分之和可以尽可能的高!
那么,小Ho该如何做呢?
提示一:树上的动态规划?其实老早就接触过了吧!
输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第一行为两个整数N、M,意义如前文所述。
每组测试数据的第二行为N个整数,其中第i个整数Vi表示标号为i的结点的评分
每组测试数据的第3~N+1行,每行分别描述一根木棍,其中第i+1行为两个整数Ai,Bi,表示第i根木棍连接的两个小球的编号。
对于100%的数据,满足N<=10^2,1<=Ai<=N, 1<=Bi<=N, 1<=Vi<=10^3, 1<=M<=N
小Hi的Tip:那些用数组存储树边的记得要开两倍大小哦!
输出
对于每组测试数据,输出一个整数Ans,表示使得涂漆结点的评分之和最高可能是多少。
样例输入
-
10 4 370 328 750 930 604 732 159 167 945 210 1 2 2 3 1 4 1 5 4 6 4 7 4 8 6 9 5 10
- 样例输出
-
2977
-
当一个节点被选择后,它的所有祖先节点也要被选择该条件换一个说法,可以解释为:只有当选择了一个节点后,我们才可以选择它的子节点。我们首先建立状态
f[i][k]
,f[i][k]
表示以i
节点为根的子树,在满足条件一的情况下,选择至多k
的节点能够得到的最大权值。则可以写出状态转移情况:- 选择i节点:
f[i][k]
等于w[i]
加上所有子节点选择k-1
个节点的最大权值 - 不选择i节点:
f[i][k] = 0
不选择i节点很好处理,那么我们如何处理选择i节点时,子节点的情况?根据题目描述,我们知道给定的节点
i
可能有多个儿子节点,不妨假设其有m
个儿子节点。则可以表示为,在m
个儿子上一共选择k-1
个节点,使得选择的节点权值之和最大。举个例子,比如样例:我们在计算f[1][4]
时,需要考虑对于以2,3,4分别为根节点子树,一共选择3个节点,来使得权值最大。也就是说在2子树中选择x
个节点,3子树中选择y
个节点,4子树中选择z
个节点,使得x+y+z=3
。很显然,该问题同样是一个动态规划问题:建立状态g[i][j]
,g[i][j]
表示前i个儿子选择j个节点时最大权值,则有状态转移过程:g[i][j] = max{g[i - 1][j - k] + f[childId][k] | k = 0 .. j}
因此我们可以得到整个动态规划的过程:
// 初始化f数组 f[][] = -1;dp(root, k):If (k == 0) ThenReturn 0;End IfIf (f[root][k] != -1) Then// 由于可能多次调用dp(root,k)// 所以这里采用了记忆化的思想Return f[root][k];End If// 不选择该节点f[root][k] = 0;// 选择该节点g[][] = 0; // 初始化g数组,需要注意g为该函数的局部变量For i = 1 .. m // 枚举子节点For j = 0 .. k - 1For t = 0 .. jIf g[i][j] < dp(child[i], t) + g[i-1][j-t] Theng[i][j] = dp(child[i], t) + g[i-1][j-t];End IfEnd ForEnd ForEnd ForIf (f[root][k] < g[m][k-1] + w[root]) Thenf[root][k] = g[m][k-1] + w[root];End IfReturn f[root][k];
- 选择i节点:
-
#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 110; int n,m,cnt,f[maxn][maxn]; int score[maxn],pre[maxn]; struct Edge {int key,next; }edge[maxn<<1];void addedge(int x,int y) {edge[cnt].key = y;edge[cnt].next = pre[x];pre[x] = cnt++; }void dfsDP(int cur,int p,int M) {if(M == 0){f[cur][M] = 0;return;}if(f[cur][M] != -1) return;int num = 0,g[maxn][maxn] = {0};for(int i = pre[cur]; i != -1; i = edge[i].next){int v = edge[i].key;if(v == p) continue;num++;for(int j = 0; j < M; j++)for(int t = 0; t <= j; t++){dfsDP(v,cur,t);if(g[num][j] < f[v][t] + g[num-1][j-t])g[num][j] = f[v][t] + g[num-1][j-t];}}if(f[cur][M] < g[num][M-1] + score[cur])f[cur][M] = g[num][M-1] + score[cur]; }int main() { while(scanf("%d%d",&n,&m)!=EOF){for(int i = 1; i <= n; i++)scanf("%d",&score[i]);memset(f,-1,sizeof(f));memset(pre,-1,sizeof(pre));cnt = 0;for(int i = 1; i < n; i++){int a,b;scanf("%d%d",&a,&b);addedge(a,b);addedge(b,a);}dfsDP(1,0,m);printf("%d\n",f[1][m]);}return 0; }
hihocoder #1055 : 刷油漆(树形dp)相关推荐
- #1055 : 刷油漆
时间限制: 10000ms 单点时限: 1000ms 内存限制: 256MB 描述 上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不 ...
- 【蓝桥杯官网试题 - 历届试题】格子刷油漆(dp)
题干: 问题描述 X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆. 你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但 ...
- nyoj 980 格子刷油漆
格子刷油漆 时间限制: 1000 ms | 内存限制: 65535 KB 难度: 3 描述 X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆. 你可 ...
- 蓝桥 历届试题 格子刷油漆
历届试题 格子刷油漆 时间限制:1.0s 内存限制:256.0MB 问题描述 X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆. 你可以从任意一个格 ...
- 树形DP——没有上司的舞会
树形DP--没有上司的舞会 题目 算法分析 Code 总结与反思 题目 Luogu:P1352 https://www.luogu.com.cn/problem/P1352 题目描述 某大学有 nnn ...
- BNUOJ 52305 Around the World 树形dp
题目链接: https://www.bnuoj.com/v3/problem_show.php?pid=52305 Around the World Time Limit: 20000msMemory ...
- [树形dp] Jzoj P5233 概率博弈
Description 小A和小B在玩游戏.这个游戏是这样的: 有一棵n个点的以1为根的有根树,叶子有权值.假设有m个叶子,那么树上每个叶子的权值序列就是一个1->m 的排列. 一开始在1号点有 ...
- fwt优化+树形DP HDU 5909
1 //fwt优化+树形DP HDU 5909 2 //见官方题解 3 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ 4 5 #include ...
- BZOJ 1040 ZJOI2008 骑士 树形DP
题目大意:给定一个基环树林,每一个点上有权值,要求选择一个权值和最大的点集,要求点集中的随意两个点之间不能直接相连 最大点独立集--考虑到n<=100W,网络流铁定跑不了,于是我们考虑树形DP ...
最新文章
- c 获取mysql列数据_转 用C API 操作MySQL数据库
- java string()函数_从Java中的String函数返回String构建器?
- Nginx详解五:Nginx基础篇之HTTP请求
- 空调系统故障类型与故障案例集
- 使用python读取mysql数据库并进行数据的操作
- 从真实项目中抠出来的设计模式——第二篇:过滤器模式
- java单个数组求积_[剑指offer][Java]构建乘积数组
- Linux CentOS 中安装 MySql
- 虚拟机安装BackTrack 5 的教程详解!
- 斐波那契数列(C语言实现)
- 上海链家网二手房成交数据爬取
- Js实现别踩白块儿小游戏
- docker 强制使用root进入容器
- DAO组织决定风险投资,Tiger DAO VC善用群体的智慧
- Django之自定义 form 表单上传图片
- ROS:AUSU Xtion Pro Live OPENNI2
- 【CS231n】十五、深度学习的高效算法和硬件设计_一只神秘的大金毛_新浪博客...
- 情侣空间单页HTML模板
- 一个Java讲师在培训过程中用到的工具【随时更新中】
- Android 面向接口编程