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\)个点的冷酷度之和最大为多少。

\(n\le 2015,f(i)\le 10000\)

分析

\(n\)个点的树的度数之和一定为\(2\times (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\n",dp[s]);
	}
	return 0;
}
posted @ 2020-09-28 19:20  xyq0220  阅读(132)  评论(0编辑  收藏  举报