http://codevs.cn/problem/1486/
我们比较熟悉二叉树,题目中给出的是一棵多叉树,我们需要将这可二叉树改造成二叉树。
二叉树可以为这样的:
父亲结点左边储存儿子,右边储存兄弟。
有两种改造方法:
①
if(tree[x].l==0)tree[x].l=y; else { int k=tree[x].l; while(tree[k].r)k=tree[k].r; tree[k].r=y; }
②
tree[y].r = tree[x].l; tree[x].l = y;
之后再考虑转移,对于这个题来说,我们想要得到关于父节点的信息,就必须先处理完它的左右子树。
注意对于每个节点,这个节点可以不取而直接去取它的兄弟。
先处理每个节点的兄弟,在每个节点枚举向左可以放多少人,向右可以放多少人,更新过程递归实现。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; int n,m; int a[1006],dp[1006][1006]; struct ahah{ int l,r; }tree[1006<<2]; int dfs(int k,int sum) { if(!sum||!k)return 0; if(dp[k][sum]!=-1)return dp[k][sum]; int ans=dfs(tree[k].r,sum); for(int i=0;i<sum;i++) { ans=max(ans,dfs(tree[k].l,i)+dfs(tree[k].r,sum-i-1)+a[k]); } dp[k][sum]=ans; return ans; } int main() { memset(dp,-1,sizeof(dp)); int x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); if(tree[x].l==0)tree[x].l=y; else { int k=tree[x].l; while(tree[k].r)k=tree[k].r; tree[k].r=y; } } printf("%d",dfs(tree[0].l,m)); }