洛谷P2014 选课 - 树上背包

本文深入探讨了DP算法的应用场景及实现细节,通过一个具体的树形DP实例来讲解如何进行状态转移与修正,以达到最优解。代码示例清晰地展示了递归与DP相结合的方法。

注意在dp中x!=0那一段 其实是对状态的修正

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 300 + 10;
int n,m,tot,head[MAXN],k[MAXN],son[MAXN],f[MAXN][MAXN];
struct Edge{
    int u,v,to;
    Edge(){}
    Edge(int u, int v, int to) : u(u), v(v), to(to) {};
}e[MAXN];
inline void add(int u, int v) {
    e[++tot] = Edge(u,v,head[u]);
    head[u] = tot;
}
void dfs(int x) {
    if(!head[x]) son[x] = 1;
    for(int i=head[x]; i; i=e[i].to) {
        dfs(e[i].v);
        son[x] += son[e[i].v];
    }
}
void dp(int x) {
    for(int i=head[x]; i; i=e[i].to) {
        int v = e[i].v;
        dp(v);
        for(int t=m; t>=0; t--) 
            for(int j=t; j>=0; j--) 
                f[x][t] = max(f[x][t], f[v][j] + f[x][t-j]);
    }
    if(x != 0) 
        for(int t=m; t>0; t--)
            f[x][t] = f[x][t-1] + k[x];
}
int main() {
    scanf("%d %d", &n, &m);
    for(int i=1; i<=n; i++) {
        int u;
        scanf("%d %d", &u, &k[i]);
        if(u != 0)
            add(u, i);
        else 
            add(0, i);// ³¬¼¶Ô´µã0 
    }
    dfs(0);
    dp(0);
    printf("%d\n", f[0][m]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值