您的位置:首页 > 其它

[HDU 5534] Partial Tree (完全背包问题) (好题)

2016-10-07 16:18 495 查看

链接

HDU 5534

题意

给出一个数n,和一组关于度(degree)的函数f(d),若某点的度为d,则提供f(d)的贡献,问n个点构成的树中最大贡献值。

题解

2015年长春赛区的1006,很不错的题目。

首先要知道一颗含有n个节点的树结构,其所有节点的度之和为2*(n-1),因为只有n-1条边;并且只要保证每个节点的度都>0,总度为2*(n-1),则一定有一个树结构对应。

由于每个点需要至少度为1,则成了,将n-2个度分给n个点,点的贡献和sum(f(di))最大为多少。

这可以转化成一个背包问题d[i][j],代表前i个节点分配j个度所获得的最大贡献值。但是这么做是超时的。

可以以度为转移的对象,容量变为n-2,度一共有n-2种,消耗分别为[1, n-2],价值为[f(2), f(n-1)],相同种类的度可以取无限种,容量不超过n-2即可(当然取的次数也不会超过n-2),变成了一个完全背包问题。

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long lint;
const lint oo = 1e16;
int f[2020];
lint dp[2020];
int main()
{
int T;
cin >> T;
while(T--)
{
int n;
cin >> n;
for(int i = 1; i <= n-1; i++)
scanf("%d", &f[i]);
for(int i = n-2; i >= 0; i--)
dp[i] = -oo;
dp[0] = n * f[1];
for(int i = 1; i <= n-2; i++)   /// Cost-type
{
for(int j = 0; j <= n-2; j++)   /// V
{
if(j >= i) dp[j] = max(dp[j], dp[j - i] + f[i + 1] - f[1]);
}
}
cout << dp[n-2] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm dp 背包