牛牛种小树
题意:
他打算用他得到的米粒去构造一棵有n个节点的树,并使得它的价值最大。
设f(d)表示树上度数为d的一个点能够获取的最大价值。则这棵树的价值为∑i=1nf(di)\sum_{i=1}^nf(d_{i})∑i=1nf(di),其中did_{i}di表示第i个点的度数
题解:
一颗n个节点的数,所有点的度数之和为2n-2
那我们可以反着理解,将这2n-2个度数分配给n个点,当然每个点至少度数为1,所以我们先给每个点分一个度数,这样问题就是n-2个度数分配给n个点,f[i]表示度为i的节点的价值。这个问题就很类似完全背包了,f[i]是价值,空间为n-2,有n-2个物品(对应度数为2和度数为n-1,因为度数为1的提前处理了)。
注意度数为1的提前处理了,所以每次加入一堆时需要减去f(1)
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#define int long long
using namespace std;
int T,i,s,j,n,a[12020],f[12020];signed main()
{scanf("%lld",&n);for (i=1;i<=n-1;i++){scanf("%lld",&a[i]);if (i!=1) a[i]-=a[1];}s=a[1]*n;for (i=1;i<=n-2;i++) f[i]=-2e18;f[0]=0;for (i=2;i<=n-1;i++)for (j=i-1;j<=n-2;j++)f[j]=max(f[j],f[j-i+1]+a[i]);printf("%lld\n",s+f[n-2]);return 0;
}