hdu 5534 Partial Tree 2015长春区域赛 dp 脑洞

来源:互联网 发布:python random.choice 编辑:程序博客网 时间:2024/04/29 19:18

题目

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5534

题目来源:2015长春区域赛第五题,银牌题。

简要题意:给定f函数,构造一颗树,令它的每个节点的度数的f函数值之和最大。

数据范围:1T2015;2n2015;0f(i)10000

题解

这题首先一个很直观的想法就是dp[i][j]i个节点j条边的最大值,然后枚举当前节点的度数。

可是复杂度是立方的,明显通不过这道题。

这题需要脑洞,比较难理解,也是很不错的一道题。

关键在于换个东西来dp,先将所有节点变为1度,然后不断增加一些节点的度数。

由于节点数和度数和最后是确定的,每个节点也肯定有度数,最终必然能够构成一棵树。

最终的度数增量为2(n1)n=n2,于是就变成了容量n2的完全背包了。

思路非常巧妙,脑洞非常大。

实现

中间的代价可能是负的,需要初始化为

可以写成二维的,也可以写成一维的。

代码

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <stack>#include <queue>#include <string>#include <vector>#include <set>#include <map>#define pb push_back#define mp make_pair#define all(x) (x).begin(),(x).end()#define sz(x) ((int)(x).size())#define fi first#define se secondusing namespace std;typedef long long LL;typedef vector<int> VI;typedef pair<int,int> PII;LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}// headconst LL MOD = 1e9+7;const int N = 2222;const int INF = -0x3f3f3f3f;int f[N];int dp[N];int main () {    int t;    scanf("%d", &t);    while (t--) {        int n;        scanf("%d",&n);        for (int i = 1; i < n; i++) scanf("%d",f+i), dp[i] = INF;        for (int i = 1; i <= n; i++) {            int temp = f[i]-f[1];            for (int j = i-1; j <= n-2; j++) {                dp[j] = max(dp[j], dp[j-i+1]+temp);            }        }        printf("%d\n", n*f[1] + dp[n-2]);    }    return 0;}
0 0