有依赖的背包问题

题目

题目传送门

题解

一道树形 DP \text{DP} DP题,令 u \text{u} u v \text{v} v父亲节点,那么转态转移方程为:
f [ u ] [ j ] = max ⁡ ( f [ u ] [ j − k ] + f [ v ] [ k ] , f [ u ] [ j ] ) f[u][j] = \max(f[u][j - k] + f[v][k], f[u][j]) f[u][j]=max(f[u][jk]+f[v][k],f[u][j])

code

#include 
using namespace std;
const int maxn = 105;

template <typename T>
inline void read(T &s) {
	s = 0;
	T w = 1, ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
	while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
	s *= w;
}

int n, m, rt, tot;
int lin[maxn], v[maxn], w[maxn], f[maxn][maxn];
struct node { int next, to; } edge[maxn];

inline int min(int aa, int bb) { return aa < bb ? aa : bb; }
inline int max(int aa, int bb) { return aa > bb ? aa : bb; }

inline void add(int from, int to) {
    edge[++tot].to = to;
    edge[tot].next = lin[from];
    lin[from] = tot;
}

void dfs(int x) {
    for (int i = lin[x]; i; i = edge[i].next) {
        int y = edge[i].to;
        // cout << "y : " << y << endl;
        dfs(y);
        for (int j = m - v[x]; j >= 0; --j) {
            for (int k = 0; k <= j; ++k) {
                f[x][j] = max(f[x][j], f[x][j - k] + f[y][k]);
            }
        }
    }
    for (int i = m; i >= v[x]; --i) { 
        f[x][i] = f[x][ i - v[x] ] + w[x];
    }
    for (int i = 0; i < v[x]; ++i) { 
        f[x][i] = 0;
    }
}

int main() {
    read(n), read(m);
    int x;
    for (int i = 1; i <= n; ++i) {
        read(v[i]), read(w[i]), read(x);
        if (x == -1)  rt = i;
        else add(x, i);
    }
    dfs(rt);
    // cout << "rt : " << rt << endl; 
    printf("%d\n", f[rt][m]);
    return 0;
}

你可能感兴趣的:(题解————题解,动态规划——动态规划,动态规划——树形dp)