Partial Tree 【HDU - 5534】【完全背包】【2015长春银牌题】

题目链接


  一道思维爆炸的题,过的有诸多不易,还好没去赛场,不然得凉,这道题想了还真挺久的。

  这道题就是问你如何用可以这么(N-1个)节点构成一棵完整的树,每个节点的可以连出去的边分别为(1,2,3,......,N-1),并且还要使得这棵树的价值最大,求该最大价值。

  挺复杂的,也是在大佬教学下才逐渐明白整个思路的,我们有N个点,用它们建树的话会有N-1条边,就意味着有2*(N-1)的度,那么,我们既要满足最后选取的节点数为N,也要使得最后的度恰为2*(N-1)==2*N-2,好麻烦!!!但是,我们得到的条件确实两个,我们可以利用边与度的关系,我们即要建N条边,那么,我们先投N个1号节点(只有一条边)进去,那么此时度就是N,换而言之,我们剩下就是为了补全N-2个度就可以了,怎么补?我们可以利用与一号节点的差值来补,相当于剔除一个一号节点,再补一个更大的节点进来,然后价值就是原价值与一号节点的差值然后就是道典型的完全背包了,使得最后满足条件即可。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=2020;
int N, a[maxN];
ll dp[maxN]={0};
int main()
{
    int T;  scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &N);
        for(int i=1; i<N; i++) { scanf("%d", &a[i]); dp[i]=-INF; }
        dp[0]=N*a[1];
        for(int i=2; i<N; i++) a[i]-=a[1];
        for(int i=1; i<=N-1; i++) dp[i]=i*a[1];
        for(int i=1; i<N-1; i++)
        {
            for(int j=i; j<=N-2; j++)
            {
                dp[j] = max(dp[j], dp[j-i]+a[i+1]);
            }
        }
        printf("%lld\n", dp[N-2]);
    }
    return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值