题目大意:
给n个点,然后建n-1条边,使其成为一颗树,然后给一个f数组,f[i]表示度数为i的点的价值为f【i】,问最大价值是多少。
题目思路:
和一个黑龙江省赛的C题很像,构成一棵树需要2*n-2条边,那么一个点至少要有一个度,所以问题转化成,n个点分n-2个度。
分配i个的时候,价值是f【i+1】,然后跑完全背包,但是问题出现了,我们怎么知道一定分给了n个点,我们不是要保证每一个都要至少一个点吗,所以我们先给每个数都分配一个度,也就是f【1】然后我们dp的时候,如果选取了商品那么就要减去他之前分配的这个度。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN = 2030;
int f[MAXN];
ll dp[MAXN][MAXN];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<=n-1;i++)
for(int j=0;j<=n-1;j++)
dp[i][j]=-0x3f3f3f3f;
dp[0][0]=0;
for(int i=1;i<=n-1;i++){
scanf("%d",&f[i]);
}
ll ans=n*f[1];
for(int i=1;i<=n-2;i++){
for(int j=0;j<=n-2;j++){
dp[i][j]=max(dp[i][j],dp[i-1][j]);
if(j>=i)dp[i][j]=max(dp[i][j],dp[i][j-i]+f[i+1]-f[1]);
}
}
printf("%lld\n",dp[n-2][n-2]+ans);
}
}