HDU-5534 Partial Tree 完全背包优化

HDU-5534 Partial Tree

题意

给出(n)个点,让你连(n-1)条边使这(n)个点构成一个树,设第(i)个点的度数为(d_i),则它的冷酷度为(f(d_i)),给出(f(1),f(2),dots,f(n-1)),问(n)个点的冷酷度之和最大为多少。

(nle 2015,f(i)le 10000)

分析

(n)个点的树的度数之和一定为(2 imes (n-1)),通俗理解为每条边提供两个度数,一共有(n-1) 条边。

将每种度数的点看做一个物品,度数为(i)的点的价值为(f(i)),重量为(i),因为要保证选择(n)个点,所以还有另一个重量(1)

然后就是一个完全背包了,但是这样做是(O(n^3))的,考虑优化,可以先给每个结点赋上一个度,就不需要那个为(1)的重量了,价值变为(f(i)-f(1)),重量变为(i-1),优化为(O(n^2))

通过下式转移即可。

(dp[j]=max(dp[j],dp[j-(i-1)]+f(i)-f(1)))

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;++i)
#define per(i,n,a) for (int i=n;i>=a;--i)
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
typedef pair<int,int> pii;
#define ll long long
const int inf=1e9;
const int mod=1e9+7;
const int N=1e5+10;
int T,n;
int f[N];
int dp[2050];
int main(){
	//ios::sync_with_stdio(false);
	//freopen("in","r",stdin);
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		rep(i,1,n-1){
			scanf("%d",&f[i]);
		}
		memset(dp,0,sizeof(dp));
		int s=n-2;
		dp[0]=n*f[1];
		rep(i,1,n-1){
			rep(j,i-1,s) dp[j]=max(dp[j],dp[j-i+1]+f[i]-f[1]);
		}
		printf("%d
",dp[s]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/xyq0220/p/13746404.html