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

来源:互联网 发布:ubuntu服务器版u盘安装 编辑:程序博客网 时间:2024/05/22 04:30

链接

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;}
0 0
原创粉丝点击