hdu 4003 Find Metal Mineral(树形DP)
来源:互联网 发布:淘宝服装店女装 编辑:程序博客网 时间:2024/04/30 16:49
题意:给一棵树,从一个节点到下一个节点需要消耗一定的能量,以最小的能量消耗遍历这棵树。
解法:首先试着思考一个问题:如果有多个机器人去往一个子节点,那有多少机器人需要回来?
假如从father节点去遍历它的子节点son,首先要明白一点如果所有的机器人都要回来,那还不如只让一个机器人去。因为在遍历一个节点的时候,如果要返回的话,那么需要消耗的能量是双倍的。比如说对于son节点,如果只去一个机器人,消耗是2*father->son->cost(注意需要返回);如果让两个机器人去,那么消耗就是4*father->son->cost。
那么多个机器人能给我们带来的好处是什么呢?
就是在不返回的情况下,某些节点我们可以少走一次(去了就不要回来了)。同样以a和b遍历son这个子树为例子,如果son还有两个son分别是son1和son2。如果我们让一个机器人去,消耗就是2*son->son1->cost+son->son2->cost;如果让两个机器人去,消耗就是son->son1->cost+son->son2->cost。可以看出来,在任何情况下,返回多个(超过一个)机器人都是不明智的,因为在这样情况下,多出的机器人并不能节省任何能源,但是在这个机器人返回son的父节点father节点的时候还需要多消耗一个father->son->cost。
解法:首先试着思考一个问题:如果有多个机器人去往一个子节点,那有多少机器人需要回来?
假如从father节点去遍历它的子节点son,首先要明白一点如果所有的机器人都要回来,那还不如只让一个机器人去。因为在遍历一个节点的时候,如果要返回的话,那么需要消耗的能量是双倍的。比如说对于son节点,如果只去一个机器人,消耗是2*father->son->cost(注意需要返回);如果让两个机器人去,那么消耗就是4*father->son->cost。
那么多个机器人能给我们带来的好处是什么呢?
就是在不返回的情况下,某些节点我们可以少走一次(去了就不要回来了)。同样以a和b遍历son这个子树为例子,如果son还有两个son分别是son1和son2。如果我们让一个机器人去,消耗就是2*son->son1->cost+son->son2->cost;如果让两个机器人去,消耗就是son->son1->cost+son->son2->cost。可以看出来,在任何情况下,返回多个(超过一个)机器人都是不明智的,因为在这样情况下,多出的机器人并不能节省任何能源,但是在这个机器人返回son的父节点father节点的时候还需要多消耗一个father->son->cost。
这时候我们再考虑遍历一个子树son所消耗的能量,在去的机器人数量不同的情况下消耗的能量是不同的。这里可以参考《背包九讲》中泛化背包的思想。至于优化方案的时候跟之前做的1011和1561不太一样,这个不只是只能取一个,还是必须去一个。开始的时候想的是把dp数组初始化为-1来解决这个问题,但是这样写起来代码需要多加一些判断还要对叶节点进行特别处理,看起来不是很美观。再然后看到了这种直接给每一个包一个初始值,然后再进行计算的方式,这样看起来代码漂亮得多。
附上大神的博客:点击打开链接
#include<stdio.h>#include<string.h>#define N 10005#define K 12int dp[N][K],ans[K][N];int n,s,k;struct node{ int son; int next; int data;}Edge[N*2];int cnt,head[N],vis[N];int Min(int x,int y){ if(x<y) return x; else return y;}void AddEdge(int x,int y,int k){ Edge[cnt].data=k;Edge[cnt].son=y;Edge[cnt].next=head[x];head[x]=cnt++; Edge[cnt].data=k;Edge[cnt].son=x;Edge[cnt].next=head[y];head[y]=cnt++; return ;}void dfs(int father){ int u=head[father]; vis[father]=1; for(int i=u;i!=-1;i=Edge[i].next) { int son=Edge[i].son; if(vis[son]) continue; dfs(son); for(int t=k;t>=1;t--) { dp[father][t]=Min(dp[father][t-1]+dp[son][1]+Edge[i].data,dp[father][t]+dp[son][0]+2*Edge[i].data); for(int j=1;j<=t;j++) dp[father][t]=Min(dp[father][t],dp[father][t-j]+dp[son][j]+j*Edge[i].data); } dp[father][0]+=dp[son][0]+2*Edge[i].data; } return ;}int main(){ while(scanf("%d%d%d",&n,&s,&k)!=EOF) { memset(head,-1,sizeof(head)); cnt=0; for(int i=1;i<n;i++) { int x,y,k; scanf("%d%d%d",&x,&y,&k); AddEdge(x,y,k); } memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); dfs(s); printf("%d\n",dp[s][k]); } return 0;}
0 0
- 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 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 Mineral 树形dp+分组背包
- hdu 4003 Find Metal Mineral (树形dp+背包)
- HDU 4003 Find Metal Mineral(树形dp + 分组背包)
- HDU 4003 Find Metal Mineral (树形DP+分组背包)
- JVM基础:JVM参数设置、分析
- js ==与===区别
- 电脑IP受限制无法连接网络的原因和解决办法
- C#三种判断字符是否为汉字的方法
- Dom4j 使用简介
- hdu 4003 Find Metal Mineral(树形DP)
- 修改UINavigationController中leftBarButtonItem按钮的title
- java读取文件细节
- C# Json数据转数组 泛型方法
- spring IOC 机制模拟实现
- C# DataTable 中实现 DISTINCT 显示不重复列
- unix exec
- java方法的重载与覆盖
- js自动检测是否已加载jquery