1. 程式人生 > 其它 >AcWing 10. 有依賴的揹包問題(圖解版)

AcWing 10. 有依賴的揹包問題(圖解版)

題目傳送門

一、思路分析

二、實現程式碼

#include <bits/stdc++.h>

using namespace std;
const int N = 110;

int f[N][N], v[N], w[N], h[N], ne[N], e[N], idx;
int n, m;

//a是b的父節點
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

//因為u是根節點,所以u是必選的
void dfs(int u) {
    //列舉子樹
    for (int i = h[u]; i != -1; i = ne[i]) {
        int son = e[i];//記錄子樹的根節點
        dfs(e[i]);//因為dfs是自下而上的,所以需要從下到上計算

        for (int j = m - v[u]; j >= 0; j--)//因為u是該樹的根節點,所以必選,預留出u的空間
            for (int k = 0; k <= j; k++)//列舉該子樹分配到的體積
                f[u][j] = max(f[u][j], f[u][j - k] + f[son][k]);//加上該子樹的值
    }
    //把物品u加進去,因為是根節點
    for (int i = m; i >= v[u]; i--) f[u][i] = f[u][i - v[u]] + w[u];
    for (int i = 0; i < v[u]; i++) f[u][i] = 0;//如果無法容納物品u,那他的價值為0;
}

int main() {
    memset(h, -1, sizeof(h));
    scanf("%d%d", &n, &m);
    int anser;
    for (int i = 1; i <= n; i++) {
        int p;
        scanf("%d%d%d", &v[i], &w[i], &p);
        if (p == -1) anser = i;//尋找出祖宗節點
        else add(p, i);
    }
    dfs(anser);
    printf("%d", f[anser][m]);
    return 0;
}