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;
}