树型DP,树上的背包
来源:互联网 发布:php base64解码图片 编辑:程序博客网 时间:2024/06/02 00:26
遇到一个题目:
金矿问题
★问题描述
有一个国家,所有的国民都非常老实憨厚,某天他们在自己的国家发现了 M 座金
矿,国王知道这个消息后非常高兴,他希望能够把这些金子都挖出来造福国民。后他找
到了这个领域的专家小八,对每一座金矿进行勘测,勘测发现挖掘每个金矿所需的人数
是固定的(一个也不需要多,一个也不能少),而且这些金矿也有主矿和副矿的区别,
主矿可以直接进行挖掘,但是副矿必须在挖掘完其对应的主矿后才能进行挖掘,否则会
有相当的风险。每个主矿可能有 0 个、1 个或 2 个副矿,每个副矿都只对应 1 个主矿,
且副矿不会再有副矿。了解完这些后,国王决定派 N 个矿工去挖金矿。(N 个矿工不一定要全部用完)
★编程任务
给出金矿数量 M 及矿工数量 N ,以及每个金矿的具体情况。求最多能获得的金子数量。
★数据输入
第 1 行为两个正整数,用一个空格隔开:
NM
(其中 N(2<=N<=100),表示所有矿工数量,M(2<=M<=1000),为金矿的数量。)
从第 2 行到第 M+1 行,第 j 行给出了编号为 j-1 的金矿的基本数据,每行有 3 个
非负整数 v p q(其中 v 表示挖掘该金矿所需的矿工数目,p 表示该金矿的含金量,q 表示该金矿是主矿还是副矿。如果 q=0,表示该金矿是主矿,如果 q>0,表示该金矿为副矿,q
是所属主矿的编号)
★数据输出输出只有一行,表示最多的金子数量。
输入文件示例 输出文件示例
100 5
80 100 0
40 500 1
20 300 1
20 100 0
50 200 0 400
虽然最开始能想到是dp,但是以为状态之间存在依赖关系,所以真的无从下手被告知是树型dp,所以去看了下树上背包入门问题 hdu 1561
Problem Description
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
Input
每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。
Output
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
Sample Input
3 2
0 1
0 2
0 3
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
0 0
Sample Output
5
13
这个题我们大致能抽象出这样的状态:
设状态 dp[i][k][j]:第i个节点,前k个子节点,该节点和它的子节点总共用了j次攻破所获得的最大收益
状态转移: dp[i][k][j]=max(dp[i][k-1][j],dp[i][k-1][p]+dp[son(i)][k-1][j-p]
这个状态的意义是:
dp[i][k-1][j]:第k个子节点不去攻破
dp[i][k-1][p]+dp[son(i)][k-1][j-p]:去攻破第k个子节点,但子节点也有孩子,所以分配的攻破次数要枚举
/* ***********************************************Author :TisuamaCreated Time :2017年10月31日 星期二 16时49分32秒File Name :挖金矿.cpp************************************************ */#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <cmath>#include <cstdlib>#include <vector>#include <queue>#include <set>#include <map>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a ) const int INF=0x3f3f3f3f;typedef long long LL; const int maxn=1e5+100;int dp[220][220];vector<int> v[220];int val[220];int vis[220];int n,m;void dfs(int f){ vis[f]=1; for(int i=0;i<v[f].size();i++) { int to=v[f][i]; if(!vis[to]) dfs(to); for(int j=m;j>=1;j--) { for(int k=1;k<=j;k++) { dp[f][j]=max(dp[f][j],dp[f][k]+dp[to][j-k]); } } } return ;}int main(){ int a,b; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; m++; for(int i=0;i<=n;i++) v[i].clear(); CLEAR(dp,0); CLEAR(vis,0); for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); v[a].push_back(i); dp[i][1]=b; } dfs(0); printf("%d\n",dp[0][m]); }}
那么回到这个题,这需要稍稍变一下,上面是分配攻破次数,我们这里分配人数
/* ***********************************************Author :TisuamaCreated Time :2017年10月31日 星期二 21时16分19秒File Name :挖金矿.cpp************************************************ */#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <cmath>#include <cstdlib>#include <vector>#include <queue>#include <set>#include <map>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a ) const int INF=0x3f3f3f3f;typedef long long LL; const int maxn=1e5+100;int dp[1100][1100];int n,m;vector<int> v[1100];int vis[1100],val[1100];void dfs(int x){ vis[x]=1; for(int i=0;i<v[x].size();i++) { int to=v[x][i]; if(!vis[to]) dfs(to); for(int j=n;j>=0;j--) { for(int k=val[x];k<=j;k++) dp[x][j]=max(dp[x][j],dp[x][k]+dp[to][j-k]); } } return ;}int main(){ int x,y,z; while(~scanf("%d%d",&n,&m)) { for(int i=0;i<=n;i++) v[i].clear(); CLEAR(dp,0); CLEAR(vis,0); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); v[z].push_back(i); dp[i][x]=y; val[i]=x; } dfs(0); printf("%d\n",dp[0][n]); }}
- 树型DP,树上的背包
- 解题报告:POJ_1155 TELE 树型DP(树上01背包)
- 树上的DP
- 树上的 DP
- HDU4003 树上的分组背包
- BZOJ5072[Lydsy十月月赛] 小A的树 解题报告【树上背包/树形DP】
- 解题报告:HDU1011 Starship Troopers 树型DP(树上01背包)
- poj 2378 树上的DP
- 技能树上的dp问题
- 树上dp的基本东西
- hdu 1561 The more, The Better(树形dp,树上背包)
- [树上依赖多重背包 DP] BZOJ 4910 [Sdoi2017]苹果树
- 【BashuOJ3520】警察局长-最短路树+树上背包+概率DP
- HDU1561 The more, The Better 解题报告【树上DP/背包】
- hihocodr1055 刷油漆 树上的背包
- 树链上的完全背包(树上倍增)
- Codeforces815C Karen And SuperMarket 解题报告【树上DP/树上背包(?)】
- hdu-4035-Maze-树上的概率dp
- 2017.10.31号作业
- 数据结构之用栈模拟队列
- 机器学习术语
- 在eclipse中配置反编译工具JadClipse
- 网络排错大讲解
- 树型DP,树上的背包
- JVM 是用什么语言写的?
- C# 操作现有Word表格详细教程
- Java 访问控制权限
- 儿童大脑发展的机会之窗
- mac phpstorm 快捷键大全
- 《计算广告》学习笔记--chap1
- js伪造Referer来路
- Java消息中间件学习笔记一 -- 什么是消息中间件?