标签:pre span div 分组 cst 状态 ring 逆序 space
/* 分组背包+树形dp:以树的深度作为阶段,以节点编号作为一维状态, 思路:首先dp[u][t]表示选择以第u门课为根,选了t门课的最大值, 状态转移方程dp[u][t]=max(所有儿子中凑出t-1门课)+s[u], 那么如何在所有儿子中凑出t-1门课,需要用到分组背包,每个儿子为一组,设v是u的一个儿子,那么第v组背包中有t-1件物品,第j件物品体积为j,价值就是dp[v][j](以v为根的选了j门课的最大值) */ #include<iostream> #include<cstring> #include<cstdio> #include<vector> using namespace std; int n,m,dp[305][305],s[305]; vector<int> son[305]; void dfs(int u){ dp[u][0]=0; for(int i=0;i<son[u].size();i++){ int v=son[u][i]; dfs(v); for(int t=m;t>=0;t--)//状态:分组背包逆序循环背包容量 for(int j=0;j<=t;j++)//决策:为什么进阶指南上要求对决策进行逆序遍历? dp[u][t]=max(dp[u][t],dp[u][t-j]+dp[v][j]); } if(u!=0)//必须算上这门课 for(int t=m;t>0;t--) dp[u][t]=dp[u][t-1]+s[u]; } int main(){ while(scanf("%d%d",&n,&m)==2){ for(int i=1;i<=n;i++){ int u; scanf("%d%d",&u,&s[i]); son[u].push_back(i); } dfs(0); printf("%d\n",dp[0][m]); } }
标签:pre span div 分组 cst 状态 ring 逆序 space
原文地址:https://www.cnblogs.com/zsben991126/p/10223733.html