您的位置:首页 > 其它

hdu 1561(树形dp)(背包dp)

2017-10-17 19:59 411 查看
传送门

题解:

设dp[pos][num]表示以pos为根的子树中选num个的最大收益。按树形背包的方式转移:

dp[p][i]=max{dp[p][i-k]+dp[son][k]}

最终答案就是dp[0][m+1]。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=204;
int n,m;
int head[MAXN],etot;
struct EDGE {
int v,nxt;
}e[MAXN];
int dp[MAXN][MAXN],siz[MAXN];
inline int read() {
int x=0;char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
inline void adde(int u,int v) {
e[etot].nxt=head[u],e[etot].v=v,head[u]=etot++;
}
void dfs(int p) {
siz[p]=1;
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
dfs(v);
siz[p]+=siz[v];
}
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
for (int j=siz[p];~j;--j)
for (int k=1;k<j;++k)
dp[p][j]=max(dp[p][j],dp[p][j-k]+dp[v][k]);
}
}
int main() {
// freopen("hdu 1561.in","r",stdin);
while (scanf("%d%d",&n,&m)&&(n||m)) {
etot=0;
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
for (int i=1;i<=n;++i) {
int u=read(),v=read();
adde(u,i);
dp[i][1]=v;
}
dfs(0);
printf("%d\n",dp[0][m+1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树形dp 背包dp