题目链接:hdu 5534 Partial Tree
首先度的总和为2(n-1),并且每个节点度不为0。如果用二维dp[i][j]表示第i个节点还剩j个度的最优值,是没问题,但是复杂度为 o(n3) 。但是其实每个节点都要分配一个度,那么我们先给每个节点分配一个度,剩下n-2的度分给n个点,可以减掉一维,dp[i]表示i个度的最优值,因为度的个数是严格小于节点个数的。背包转移的权值为val[i]-val[1](可能有负数)
#include
#include
#include
using namespace std;
const int maxn = 3000;
const int inf = 0x3f3f3f3f;
int N, F[maxn], dp[maxn];
int solve (int n) {
for (int i = 0; i <= n; i++) dp[i] = -inf;
dp[0] = 0;
for (int i = 2; i < N; i++) {
for (int j = 0; j + i - 1 <= n; j++)
dp[i+j-1] = max(dp[i+j-1], dp[j] + F[i]);
}
return dp[n];
}
int main () {
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%d", &N);
for (int i = 1; i < N; i++) scanf("%d", &F[i]);
int ans = F[1] * N;
for (int i = 2; i < N; i++) F[i] -= F[1];
printf("%d\n", ans + solve(N-2));
}
return 0;
}