2015区域赛 长春赛区 H题
#Description
有n个点,形成生成树,每个度的权值给出
求一种生成树,使得最后总和最大
#Algorithm
完全背包问题
体积为V的背包,有N种物品,每种物品的价值是wi, 体积是vi,有无限多个,求最优放法?
关系:
总共有2(n-1)个度,有n-1种度,每种度的权值是a[i],占一个度,有无限多个,求最优?
限制:
每个点至少有1个度
改进:
不妨,先减去n个度,同时每个度的权值减去a[0]
问题变成 n-2个度中,有n-1种度,每种度的权值是a[i] - a[0]
动态规划:
dp[i]表示度数为i时的最大权值和
对于度数为i的权值a[i - 1],由于之前已经减过一次 所以度数要减1
dp[j + i] = max(dp[j + i], dp[j] + a[i])
#Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
using namespace std;
const int maxn = 2015 + 9;
const int INF = INT_MAX;
int a[maxn];
int dp[maxn]; //度数之和为i的最大值
void solve() {
memset(a, 0, sizeof(a));
int n;
scanf("%d", &n);
for (int i = 0; i < n - 1; ++i) {
scanf("%d", &a[i]); // 0..n-2
}
int ans = a[0] * n;
for (int i = 1; i < n - 1; ++i) {
a[i] -= a[0];
}
fill(dp, dp + n, -INF);
dp[0] = 0; //1个度数都没用 花费0
for (int i = 1; i < n - 1; ++i) {
for (int j = 0; i + j < n; ++j) {
dp[j + i] = max(dp[j + i], dp[j] + a[i]);
}
}
ans += dp[n - 2];
cout << ans << endl;
}
int main() {
// freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
}

被折叠的 条评论
为什么被折叠?



