HDU - 5534 Partial Tree (完全背包)

题意

要构建一棵n个点的树,树的权值为所有结点的权值和,每个结点的权值为\(f(d)\),d为结点的度数。

分析

n个结点的树,n-1条边,即度数和为2n-2。每个结点的度数至少为1,所以先令每个结点的度数为1。剩下n-2的的度数再分配掉,将这个过程转化为完全背包,每个度数可以出现的次数不限。dp[i][j] 表示在前i个度数中选择度数和为j的情况的最优值。\(dp[1][0]= n*f[1]\),表示已经将所有点初始化为度数为1。
状态转移方程:\(dp[i][j] = max(dp[i-1][j],dp[i][j-i+1]+f[i]-f[1])\)
因为之和前一维有关,可以省去第一个维度。

#include<bits/stdc++.h>
using namespace std;
#define eps 1e-7
const int maxn = 1e5+5;
typedef long long LL;
int dp[maxn];
int v[maxn];
const int INF = 0x3f3f3f3f;

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int T; scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<n;++i){
            scanf("%d",&v[i]);
        }
        memset(dp,-INF,sizeof(dp));
        dp[0] = n*v[1];
        for(int i=2;i<n;++i){
            for(int j=0;j+i-1<=n-2;++j){
                dp[j+i-1] = max(dp[j+i-1], dp[j]+v[i]-v[1]);
            }
        }
        printf("%d\n",dp[n-2]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiuwenli/p/9826256.html