HDU 4003 Find Metal Mineral 树上分组背包
来源:互联网 发布:高效程序员的狂暴之路 编辑:程序博客网 时间:2024/06/03 06:24
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4003
题意:一颗有根树N个节点的树和K个机器人,问把所有点都走到的最小花费
树上分组背包问题
这道题有一个要求就是这个机器人走完一颗树之后,还是可以回到树的根节点的,但也可以又机器人走这颗子树后不回到树根。
但是我们只要仔细的分析一下就可以看出来,假如一颗子树存在又机器人进去后又走回到树根,那么这个树只可能只放了一个机器人,且这个机器人走完这颗子树后回到树根。
情况1.有p(p > 1 )个机器人走这颗树,且它们都回到了树根。此时的花费是:子树边权和加上p个机器人回到根节点的路径和。此时假如只有一个机器人走这颗子树,花费为:子树边权和加上一条回到树根的路劲和。所以一个机器人的花费一定小于p个机器人的花费
情况2.有p(p > 1 )个机器人走这颗树,只有一个机器人回到了根节点,此时的花费和一个机器人走又回来是一样的:子树边权和加上一条回到树根的路径和。所以我们可以去掉剩下p - 1个没有回到根节点的机器人,这样不会更差还能节省机器人。
情况3.有p(p > 1) 个机器人走这颗子树,有q(1 < q < p)个机器人回到树根,那么同样花费为树上边权和 加上 p个回到树根的路径和,用一个机器人代替能得到更优的答案。
以上,在最优状态关于有机器人会回到树根的时候,只可能是1个机器人进入然后回到这个树根。
于是我们用
i = 0,对于子树rt有1个机器人进入然后又回到树根
i > 0,对于子树rt又i个机器人进入没有回到树根
对于每一颗子树,都做一个分组背包,每一个儿子的不同情况分到一组。背包容量为机器人个数k,物品价值为dp[son][j],代价为[j]。
i == 0 :
i>0:
代码:
#include <bits/stdc++.h>#define sf scanf#define pf printfusing namespace std;const int maxn = 10000 + 5,maxm = 10 + 5,INF = 0x3f3f3f3f;int n,s,k;struct edge{ int v,c,pre;}edges[maxn * 2];int head[maxn],tot;void init_edge(){ memset(head,-1,sizeof head),tot = 0;}void Insert_Edge(int u,int v,int c){ edges[tot].c = c; edges[tot].v = v; edges[tot].pre = head[u]; head[u] = tot++;}int dp[maxn][maxm];/** dp[i][0] 表示第i个子树中放入了1个机器人 且这个机器人走完这个树后 回到节点i */void DFS(int rt,int fa){ memset(dp[rt],0,sizeof dp[rt]); for(int i = head[rt];~i;i = edges[i].pre){ //背包分组 int v = edges[i].v,c = edges[i].c; if(v == fa) continue; DFS(v,rt); //分组背包 //枚举容量 for(int j = k;j >= 0;--j){ dp[rt][j] += dp[v][0] + 2 * c; //枚举物品 for(int p = 1;p <= k;++p){ if(p > j) break; dp[rt][j] = min(dp[rt][j],dp[rt][j - p] + dp[v][p] + c * p); } } }}int main(){ while(~sf("%d %d %d",&n,&s,&k)){ init_edge(); for(int i = 1;i < n;++i){ int u,v,c;sf("%d %d %d",&u,&v,&c); Insert_Edge(u,v,c); Insert_Edge(v,u,c); } DFS(s,0); int ans = INF; for(int i = 0;i <= k;++i) ans = min(ans,dp[s][i]); pf("%d\n",ans); } return 0;}
- HDU 4003 Find Metal Mineral 树上分组背包
- HDU-4003 Find Metal Mineral (树上背包)
- hdu 4003 Find Metal Mineral (树形dp+分组背包)
- (中等) 树形分组背包 HDU 4003 Find Metal Mineral
- hdu 4003 Find Metal Mineral 【树形dp,分组背包】
- hdu 4003 Find Metal Mineral(树形DP+分组背包)
- hdu 4003 Find Metal Mineral 树形dp+分组背包
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- HDU 4003 Find Metal Mineral(树形dp + 分组背包)
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- HDU 4003 Find Metal Mineral (树形DP+分组背包)
- HDU 4003 Find Metal Minaral 树上瞎搞分组背包
- hdu 4003 Find Metal Mineral(树形DP+分组背包,每个物品必须只能选一次)
- hdu 4003 Find Metal Mineral
- HDU 4003 Find Metal Mineral
- hdu 4003 Find Metal Mineral
- HDU 4003Find Metal Mineral
- hdu 4003 Find Metal Mineral
- Synchronize 和 volitile 的区别(1)
- nginx
- 第四次作业
- 为您解惑:JS模块与命名空间的介绍........
- [普及] NOIP 2014 子矩阵
- HDU 4003 Find Metal Mineral 树上分组背包
- TabLayout的使用及封装
- 22、Java入门—反射之获取获取成员变量和构造函数的信息
- excel+unittest
- iOS 开发 Certificate和Code Signing--证书与签名--详解
- RabbitMQ 入门 Helloworld
- 微信小程序例子——获取手机网络状态
- 乱搞
- [React-native]第一行代码Helloworld及集成已有项目的方案