HDU5534
题意:
- 每个结点都有一个度数,每个度数都对应一个值。为了构成一棵树,最大值为多少。
题解:
普通思路
- 点的个数为无限多个,所以为完全背包问题。。
- 每个点都是一件物品,其体积为度数,价值为度数对应的值,背包容量为2*(n-1)。我们要找n个点,使总价值最大。所以题目有两个限制,价值和数量,这是一个二维背包问题。
- dp[k][i][j]表示考虑到第k种点,总度数为i,且有j个点的最大价值。滚动数组优化,但是之后TLE。
优化
- 因为要满足必须要有n个点,所以我们先给每一个点分配一个度数,这样就保证能构成一棵树。
- 所以问题转化成了背包容量为n-2,有n-1个物品装进去,使价值最大。普通的一维完全背包问题。
- 实际上上面的方案有一点猜想在里面,如果知道证明的大佬,可以指教指教。
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 2200;
int const inf = 0x7f7f7f7f;
int T,n,m;
int val[N];
int dp[N];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n-1;i++) //最多只有n-1个度
scanf("%d",&val[i]);
m = n - 2; //背包容量,总的度数
memset(dp,-inf,sizeof(dp));
dp[0] = 0;
for(int i=2;i<=n-1;i++){
val[i] -= val[1];
for(int j=i-1;j<=m;j++)
dp[j] = max(dp[j],dp[j-i+1]+val[i]);
}
printf("%d\n",n*val[1]+dp[m]);
}
return 0;
}