hdu 3593 分类: hdu 2015-08-09 16:43 12人阅读 评论(0) 收藏
2015-08-09 16:43
471 查看
终于理解树形依赖背包啦~
这个树形DP的转移方程还是比较简单的。
树形依赖背包的优化:
设当前结点为 x,因为选取物品 x 需要强制选取物品 fa(x),
所以直接令 dp(x)=dp(fa(x)) 并限制背包空间,然后处理 dp(son(x)),
最后强制加入物品 x,即用 dp(x)+g(x)来更新 dp(fa(x)) 即可。
这样就在强制选取物品 fa(x) 的前提下,选择了物品 x。
与原问题相比,优化了泛化物品的合并,时间复杂度降到 O(G)
时间复杂度:O(N∗G)
另外这题数据有点小问题,读入部分要改成奇怪的方式才能过。。。QwQ
这个树形DP的转移方程还是比较简单的。
树形依赖背包的优化:
设当前结点为 x,因为选取物品 x 需要强制选取物品 fa(x),
所以直接令 dp(x)=dp(fa(x)) 并限制背包空间,然后处理 dp(son(x)),
最后强制加入物品 x,即用 dp(x)+g(x)来更新 dp(fa(x)) 即可。
这样就在强制选取物品 fa(x) 的前提下,选择了物品 x。
与原问题相比,优化了泛化物品的合并,时间复杂度降到 O(G)
时间复杂度:O(N∗G)
另外这题数据有点小问题,读入部分要改成奇怪的方式才能过。。。QwQ
void init() { for(int i = 1, father; i <= N; i++) { // read(cost[i]), read(att[i]), read(fa[i]); scanf("%d%d%d", &cost[i], &att[i], &father); if(father == i) father = 0; NewEdge(father, i); } }
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <vector> #include <utility> #include <stack> #include <queue> #include <iostream> #include <algorithm> template<class Num>void read(Num &x) { char c; int flag = 1; while((c = getchar()) < '0' || c > '9') if(c == '-') flag *= -1; x = c - '0'; while((c = getchar()) >= '0' && c <= '9') x = (x<<3) + (x<<1) + (c-'0'); x *= flag; return; } template<class Num>void write(Num x) { if(x < 0) putchar('-'), x = -x; static char s[20];int sl = 0; while(x) s[sl++] = x%10 + '0',x /= 10; if(!sl) {putchar('0');return;} while(sl) putchar(s[--sl]); } const int maxn = 1e5+50, maxG = 10005, rem = 505; int N, G, dp[rem][maxG]; int cost[maxn], att[maxn], fa[maxn]; struct Edge { int v, next; Edge(int v = 0,int next = 0):v(v),next(next){} }edge[maxn]; int head[maxn], el = 0; void NewEdge(int u,int v) { edge[++el] = Edge(v, head[u]), head[u] = el; } void dfs(int a,int size) { for(int i = head[a]; i; i = edge[i].next) { int p = edge[i].v; if(!head[p]) { for(int j = size; j >= cost[p]; j--) dp[a][j] = std::max(dp[a][j], dp[a][j - cost[p]] + att[p]); } else { if(size >= cost[p]) { for(int j = 0; j <= size - cost[p]; j++) dp[p][j] = dp[a][j]; dfs(p, size - cost[p]); for(int j = size; j >= cost[p]; j--) dp[a][j] = std::max(dp[a][j], dp[p][j - cost[p]] + att[p]); } } } } void clear() { el = 0, cost[0] = att[0] = 0; memset(head, 0, sizeof(head)); memset(dp, 0, sizeof(dp)); } void init() { for(int i = 1; i <= N; i++) { read(cost[i]), read(att[i]), read(fa[i]); if(fa[i] == i) fa[i] = 0; NewEdge(fa[i], i); } } int main() { #ifndef ONLINE_JUDGE freopen("3593.in","r",stdin); freopen("3593.out","w",stdout); #endif while(scanf("%d%d",&N,&G) != EOF) { clear(), init(); dfs(0, G); write(dp[0][G]), puts(""); } #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif return 0; }
相关文章推荐
- LeetCode(20)Valid Parentheses
- leetcode_242——Valid Anagram (字典法)
- 第三周工作周报
- java synchronized静态同步方法与非静态同步方法,同步语句块
- ListView上拉加载更多
- Java回顾之I/O
- php框架laravel学习 二 (数据库建立迁移与建模)
- UVA 152 Tree's a Crowd
- 二叉搜索树的基本操作(查找、插入、删除)【数据结构】
- LGPL 与GPL的区别
- SEO在网页制作中的应用
- Java io文件操作(按字符、字节、行、随机读取,追加,文件操作)
- ubuntu更换阿里源
- HDU 5366-The mook jong(组合数学)
- java中classpath的详解
- STL学习笔记--序列式容器
- 沐雪微信2.0最新版本升级啦
- conn.setAutoCommit()用法及作用
- 架构师要以自己的编程能为依托
- 关于Android Canvas.drawText方法中的坐标参数的正确解释