zoukankan      html  css  js  c++  java
  • 题解【AcWing10】有依赖的背包问题

    题面

    树形 DP 的经典问题。

    我们设 (dp_{i,j}) 表示当前节点为 (i),当前节点的子树(包含当前节点)最多装的体积是 (j) 的最大价值。

    我们遍历节点的过程就相当于做了一遍分组背包。

    注意遍历完所有子节点后要更新一下状态。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 103;
    
    int n, m;
    int tot, head[maxn], ver[maxn * 2], nxt[maxn * 2];
    int dp[maxn][maxn];
    int v[maxn], w[maxn], p[maxn];
    
    inline void add(int u, int v)
    {
        ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
    }
    
    void dfs(int u, int f)
    {
        for (int i = head[u]; i; i = nxt[i]) //循环组数
        {
            int vv = ver[i];
            if (vv == f) continue;
            dfs(vv, u); //遍历子节点
            for (int j = m - v[u]; j >= 0; j-=1) //循环体积
                for (int k = 0; k <= j; k+=1) //循环决策
                    dp[u][j] = max(dp[u][j], dp[u][j - k] + dp[vv][k]); //状态转移
        }
        //更新状态
        for (int i = m; i >= v[u]; i-=1) dp[u][i] = dp[u][i - v[u]] + w[u]; 
        for (int i = 0; i < v[u]; i+=1) dp[u][i] = 0; 
    }
    
    int main()
    {
        cin >> n >> m;
        int rt = -1; //根节点
        for (int i = 1; i <= n; i+=1) 
        {
            cin >> v[i] >> w[i] >> p[i];
            if (p[i] == -1) rt = i;
            else add(i, p[i]), add(p[i], i); //建树
        }
        dfs(rt, 0);
        cout << dp[rt][m] << endl;
        return 0;
    }
    
  • 相关阅读:
    k8s使用
    7月3日课堂笔记
    7月6日课堂笔记
    画倒三角形
    6月29日课堂笔记
    understand试用笔记一阅读VS2010项目
    Spring Boot 入门(九)使用RabbitMQ
    Spring Boot 入门(十一)使用Schedule
    Spring Boot 入门(十三)使用Elasticsearch
    学习MySQL
  • 原文地址:https://www.cnblogs.com/xsl19/p/12337084.html
Copyright © 2011-2022 走看看