[树形dp]蓝桥杯-生产车间

#include <bits/stdc++.h>  
#define ll long long
#define pll pair<int,int>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;  
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
const int N=1e6+7;
const int mod=1e9+7;
void solve(){
    int n;
    cin>>n;
    vector<int>w(n+3);
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
    }
    vector<int>g[N];
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    vector<vector<bool>>dp(n+3,vector<bool>(1003,false));
    auto dfs=[&](auto &&self,int u,int fa)->void
    {
        if(g[u].size()==1 && g[u][0]==fa)
        {
            dp[u][w[u]]=1;
            return;
        }
        dp[u][0]=1;
        for(auto v:g[u])
        {
            if(v==fa)continue;
            self(self,v,u);
            for(int i=w[u];i>=0;i--)
            {
                for(int j=0;j<=w[v] && j<=i;j++)
                {
                    if(dp[u][i]==1)continue;
                    else dp[u][i]=dp[u][i-j]&dp[v][j];
                }
            }
        }
        return;
    };
    dfs(dfs,1,-1);
    int ans=0;
    for(int i=1;i<=1000;i++)
    {
        if(dp[1][i])ans=max(ans,i);
    }
    cout<<ans<<endl;
    return ;
}
signed main (){
    IOS;
    int _=1;
    //cin>>_;
    while(_--){
        solve();
    }
    return 0;
}
/*

*/

分析:一棵树,只有叶子节点才有价值,其余每个节点的值为当前背包的容积,求最高价值。
每个节点可能有多个值,但只选一个,可以看出是分组背包。
dp[u][i]=dp[u][i] || (dp[u][i-j]&dp[v][j]);

posted on 2025-05-15 14:21  王不留航  阅读(19)  评论(0)    收藏  举报