# 背包专题

01背包：

f[i][j] = max(f[i - 1][j], f[i - 1][j - c[i]] + v[i]);

for i 1...n

for j V...c[i]

f[j] = max(f[j], f[j - c[i]] + v[i]);

for i 1...n

for j c[i]...V

f[j] = max(f[j], f[j - c[i]] + v[i]);

• 拆成01背包(过水)
• 二进制拆分(不会)
• 单调队列优化(上课讲了，没听懂...)

for i 1...g

for j V...g[i].min_c

for k g[i].s...g[i].t

if(j >= c[k])

f[j] = max(f[j], f[j - c[k]] + v[k]);

for i 1...n

for jA VA...cA[i]

for jB VB...cB[i]

f[jA][jB] = max(f[jA][jB], f[jA - cA[i]][jB - cB[i]] + v[i]);

 1 #include <cstdio>
2 #include <algorithm>
3
4 const int N = 310;
5
6 struct Edge {
7     int nex, v;
8 }edge[N]; int top;
9
10 int e[N], v[N], f[N][N], n, m, root;
11
12 inline void add(int x, int y) {
13     top++;
14     edge[top].v = y;
15     edge[top].nex = e[x];
16     e[x] = top;
17     return;
18 }
19
20 void DFS(int x) {
21     for(int i = e[x]; i; i = edge[i].nex) {
22         int y = edge[i].v;
23         DFS(y);
24         // cal
25         for(int j = m; j >= 1; j--) { // 0 1 pack
26             for(int k = 0; k <= j; k++) {
27                 f[x][j] = std::max(f[x][j], f[x][j - k] + f[y][k]);
28             }
29         }
30     }
31     if(x != root) {
32         for(int i = m; i >= 1; i--) {
33             f[x][i] = f[x][i - 1] + v[x];
34         }
35     }
36     return;
37 }
38
39 int main() {
40     scanf("%d%d", &n, &m);
41     root = n + 1;
42     for(int i = 1, x; i <= n; i++) {
43         scanf("%d%d", &x, &v[i]);
44         add(x ? x : root, i);
45     }
46     DFS(root);
47     printf("%d", f[root][m]);
48     return 0;
49 }
AC代码

posted @ 2018-06-04 13:14  garage  阅读(...)  评论(...编辑  收藏