【Luogu P2014 选课】【树形背包学习笔记】
2018-01-12 10:30
281 查看
Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)] —— By Candy?
因为依赖关系是以森林的形式给出的,增加一个虚拟节点 0 为所有无先修课节点的根。
f[i][j] 表示以 i 为根的子树中选 j 个(对应到原树中即是在节点 i 的儿子和兄弟中选 j 个)的最大价值,初始化 −inf,f[i][0]=0(不选可行),f[i][1]=wi(选一个必须选根)。
f[u][j]=max(f[u][j],max(f[u][j−k]+f[v][k],k∈[0,j−1]))
f[i][j] 就是相当于节点 i 有个容量为 j 的背包,有 s 个儿子,物品就有 s 组,每组物品价值为 f[si][0]...f[si][节点数],体积为 0...节点数。
然后就是分组背包,每组只能选一个物品,要使价值最大,也就是对于每组枚举选几件和枚举体积。
因为依赖关系是以森林的形式给出的,增加一个虚拟节点 0 为所有无先修课节点的根。
f[i][j] 表示以 i 为根的子树中选 j 个(对应到原树中即是在节点 i 的儿子和兄弟中选 j 个)的最大价值,初始化 −inf,f[i][0]=0(不选可行),f[i][1]=wi(选一个必须选根)。
f[u][j]=max(f[u][j],max(f[u][j−k]+f[v][k],k∈[0,j−1]))
精♂妙的理解
f[i][j] 就是相当于节点 i 有个容量为 j 的背包,有 s 个儿子,物品就有 s 组,每组物品价值为 f[si][0]...f[si][节点数],体积为 0...节点数。
然后就是分组背包,每组只能选一个物品,要使价值最大,也就是对于每组枚举选几件和枚举体积。
代码
#include <bits/stdc++.h> using namespace std; const int N = 305; struct Edge { int to, next; }e[N << 1]; int n, m; int w , head ; int cnt = 0; void add(int u, int v) { e[++ cnt].to = v; e[cnt].next = head[u]; head[u] = cnt; } int son ; void dfsson(int u) { for (int i = head[u]; i; i = e[i].next) { int v = e[i].to; dfsson(v); son[u] += son[v]; son[u] = min(son[u], m); } } int f ; void dfs(int u) { for (int i = head[u]; i; i = e[i].next) { int v = e[i].to; dfs(v); for (int j = son[u]; j >= 0; j --) // 背包容量 for (int k = 0; k <= j - 1; k ++) // item of group f[u][j] = max(f[u][j], f[u][j - k] + f[v][k]); } } int main() { memset(son, 0, sizeof(son)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++) { int fa; scanf("%d%d", &fa, &w[i]); add(fa, i); son[fa] ++; } memset(f, -1, sizeof(f)); for (int i = 0; i <= n; i ++) f[i][0] = 0, f[i][1] = w[i]; dfsson(0); for (int i = 0; i <= n; i ++) son[i] ++; // 因为新加了虚拟根节点 0,所以要多选一门学分为 0 的课程节点 0 dfs(0); printf("%d\n", f[0][son[0]]); return 0; }
相关文章推荐
- luogu P2014 选课 树形背包
- 洛谷 p2014 [CTSC2001] 选课 树形背包DP
- [Luogu2014]选课 树形DP
- 树形DP——Luogu2014 选课
- P2014 选课(树形背包)
- Luogu P2014 选课___背包+树形dp
- iOS: 学习笔记, 透过Boolean看Swift(译自: https://developer.apple.com/swift/blog/ Aug 5, 2014 Boolean)
- 关于SQLServer2005的学习笔记——树形结构问题
- Codevs_P1378 选课(树形DP+分组背包)
- 2014-02学习笔记
- 开源编译器学习笔记04(VC6 动态节点数组——AddNode)——2014_1_31
- 学习笔记-01背包、完全背包、多重背包
- 学习笔记——SQL SERVER2014内存数据库
- 编译原理学习笔记06——(连连看—准备一下很多课件都演示的公式E → E+T | T )——2014_1_22
- 【笔记】【算法学习】【动态规划】背包问题总结(1)
- 开源编译器学习笔记03(VC6 词法扫描器 ——动态内存先放一边)——2014_1_30
- 01背包 学习笔记
- 学习笔记:vijos1412[多人背包] 背包k优解...
- 编译原理学习笔记02——(对最基本文法的理解)——2014_1_12
- 游戏开发学习笔记(七)开发背包系统