P2015 二叉苹果树 背包树形dp入门

P2015 二叉苹果树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 

背包树形dp主要是用来处理 可以取若干个子节点若干个情况,来实现dp转移到父节点

我们令dp[x][y][i]为先取第x个节点下,前y个子节点留i条边的最大值。

转移: if(j!=0) dp[x][y][i]=max(dp[x][y][i],dp[x][y-1][i-j-1]+d[v][v的子节点的个数][j]+val[x][y])  第y个子节点的编号为v,注意x与v之间原本就有一条边

    if(j==0) dp[x][y][i]=max(dp[x][y][i],dp[x][y-1][i]+d[v][v的子节点的个数][0])

显然y这层可以用削掉,只不过 i 这层便要逆这来.

转移: if(j!=0) dp[x][i]=max(dp[x][i],dp[x][i-j-1]+d[v][j]+val[x][y])  第y个子节点的编号为v,注意x与v之间原本就有一条边

    if(j==0) dp[x][i]=max(dp[x][i],dp[x][i]+d[v][0])=dp[x][i]

最后的答案便是:dp[1][m];

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back   
#define popb pop_back  
#define fi first
#define se second
const int N=210;
//const int M=;
//const int inf=0x3f3f3f3f;     
//const ll INF=0x3ffffffffffff;
int T,n,m,val[N][N],dp[N][N];
vector<int> g[N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
void dfs(int x,int fa)
{
    for(auto v:g[x])
    {
        if(v==fa) continue;
        dfs(v,x);    
    }    
    for(auto v:g[x])
    {
        if(v==fa) continue;
        for(int j=m;j;j--)
            for(int k=1;k<=j;k++) 
                dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[v][k-1]+val[x][v]);
    }

}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
    n=read();m=read();
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read(),t=read();
        g[u].pb(v);g[v].pb(u);
        val[u][v]=val[v][u]=t;
    }
    dfs(1,0);
    printf("%d",dp[1][m]);
    return 0;
}

 

posted @ 2023-03-12 19:13  QAQ啥也不会  阅读(14)  评论(0编辑  收藏  举报