• libreoj #10153 树形dp


    $des$

    有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 NNN 个节点,标号 1 至 N,树根编号一定为 1

    我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果

    $sol$

    树形dp

    $f_{i, j}$ 表示以 $i$ 为根的子树中保留 $j$ 个的最大值

    转移时枚举该子树保留了多少以及两个儿子分别保留了多少

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define Rep(i, a, b) for(int i = a; i <= b; i ++)
    
    const int N = 105;
    
    vector <pair <int, int> > G[N];
    int n, Q;
    int f[N][N];
    
    void Dfs(int u, int fa) {
        int S = G[u].size();
        int v1 = -1, w1, v2 = -1, w2;
        Rep(i, 0, S - 1) {
            pair<int, int> P = G[u][i];
            if(P.first == fa) continue;
            if(v1 == -1) v1 = P.first, w1 = P.second;
            else v2 = P.first, w2 = P.second;
            if(v1 == -1 || v2 == -1) continue;
            Dfs(v1, u);
            Dfs(v2, u);
            Rep(q, 1, Q) {
                Rep(l, 0, q) {
                    int r = q - l;
                    if(l == 0) f[u][q] = max(f[u][q], f[v2][r - 1] + w2);        
                    else if(r == 0) f[u][q] = max(f[u][q], f[v1][l - 1] + w1);    
                    else f[u][q] = max(f[u][q], f[v1][l - 1] + w1 + f[v2][r - 1] + w2);
                }
            }
        }
    }
    
    int main() {
        cin >> n >> Q;
        Rep(i, 1, n - 1) {
            int u, v, w; cin >> u >> v >> w;
            G[u].push_back(make_pair(v, w));
            G[v].push_back(make_pair(u, w));
        }
        Dfs(1, 0);
        cout << f[1][Q];
        return 0;
    }
  • 相关阅读:
    寻找我编程道路的明灯
    Torque2D MIT 学习笔记(7) TAML的使用
    Torque2D MIT 学习笔记(4) 脚本语法(2)
    C++输入/输出流
    设计模式之命令模式
    设计模式之策略模式
    Torque2D MIT 学习笔记(11) 资源管理(3)
    C++文件处理
    Torque2D MIT 学习笔记(2) 目录结构
    设计模式之观察者模式
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9874707.html
Copyright © 2020-2023  润新知