POJ 2486 Apple Tree (树形DP,树形背包)
2015-09-20 21:55
429 查看
题意:给定一棵树图,一个人从点s出发,只能走K步,每个点都有一定数量的苹果,要求收集尽量多的苹果,输出最多苹果数。
思路:
既然是树,而且有限制k步,那么树形DP正好。
考虑1个点的情况:(1)可能在本子树结束第k步(2)可能经过了j步之后,又回到本节点(第k步不在本子树)
第二种比较简单,背包一下,就是枚举给本节点的孩子t多少步,收集到最多苹果数。第一种的话要求第k步终止于本节点下的某个子树中,那么只能在1个孩子子树中,所以应该是【其他孩子全部得走回来】+【本孩子不要求走回来】 or 【其他某个孩子中不走回来】+【本节点走回来】。
用两个DP数组区分下“回”与“不回”就行了,注意,“不回”只能有1个孩子不要求其走回来,“回”是全部回。而“不要求回来”收集到的苹果数必定大于等于“要求回来”。
AC代码
思路:
既然是树,而且有限制k步,那么树形DP正好。
考虑1个点的情况:(1)可能在本子树结束第k步(2)可能经过了j步之后,又回到本节点(第k步不在本子树)
第二种比较简单,背包一下,就是枚举给本节点的孩子t多少步,收集到最多苹果数。第一种的话要求第k步终止于本节点下的某个子树中,那么只能在1个孩子子树中,所以应该是【其他孩子全部得走回来】+【本孩子不要求走回来】 or 【其他某个孩子中不走回来】+【本节点走回来】。
用两个DP数组区分下“回”与“不回”就行了,注意,“不回”只能有1个孩子不要求其走回来,“回”是全部回。而“不要求回来”收集到的苹果数必定大于等于“要求回来”。
//#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <iostream> #define pii pair<int,int> #define INF 0x3f3f3f3f3f3f3f3f #define LL long long using namespace std; const int N=210; struct node { int from,to,next; node(){}; node(int from,int to,int next):from(from),to(to),next(next){}; }edge[N*2]; int edge_cnt, head , w ; void add_node(int from,int to) { edge[edge_cnt]=node(from, to, head[from]); head[from]=edge_cnt++; } /* dp[][][1] 记录每次都回到本节点的。 dp[][][0] 记录仅1次不回到本节点的。 */ int dp [2]; void DFS(int t,int far,int m) { node e; for(int j=0; j<=m; j++) dp[t][j][0]=dp[t][j][1]=w[t]; //既然能到这,至少带上本节点 if(m==0) return; for(int i=head[t]; i!=-1; i=e.next) { e=edge[i]; if( e.to^far ) { DFS(e.to, t, m-1); for(int j=m; j>0; j-- ) { for(int k=0; k+2<=j; k++ ) { //所有分支都回。 dp[t][j][1]=max( dp[t][j][1], dp[t][j-k-2][1]+dp[e.to][k][1] ); //本分支要回,但在其他分支不回。因为已经有1个不回了,所以更新在‘[0]’中。 dp[t][j][0]=max( dp[t][j][0], dp[t][j-k-2][0]+dp[e.to][k][1] ); } for(int k=0; k+1<=j; k++ ) { //不回,但其他分支就必须全回。 dp[t][j][0]=max( dp[t][j][0], dp[t][j-k-1][1]+dp[e.to][k][0] ); } } } } } int main() { //freopen("input.txt", "r", stdin); int n, K, a, b; while(~scanf("%d%d",&n,&K)) { edge_cnt=0; memset(head, -1, sizeof(head)); for(int i=1; i<=n; i++) scanf("%d",&w[i]); for(int i=1; i<n; i++) { scanf("%d%d",&a,&b); add_node(a,b); add_node(b,a); } DFS(1, -1, K); cout<<dp[1][K][0]<<endl; } return 0; }
AC代码
相关文章推荐
- 相机App简介
- 【IOS 开发学习总结-OC-10】★ objective-c面向对象之——成员变量,模拟类变量,单例模式
- Android开发碰到的要点
- ios-新浪微博开发-23-加载微博数据
- ios-新浪微博开发-22-封装标题按钮
- ios-新浪微博开发-21-获取用户昵称
- unity3d实现场景截图
- ios-新浪微博开发20-控制器的切换
- ios-新浪微博开发19-账号存储工具类
- ios-新浪微博开发-18-(授权存储账号信息)用归档实现
- Android Content Provider
- Using RequireJS in AngularJS Applications
- DrawerLauyout 全屏
- Android---自定义ViewGroup
- cocos2d-x Scale9Sprite的使用方法 lua篇
- iOS 中常用的四种数据持久化的方法
- iOS ARC简要介绍
- 使用java编写的冒泡排序小程序
- iOS崩溃堆栈符号化,定位问题分分钟搞定!
- objective - 在LLDB中的调用