zoukankan      html  css  js  c++  java
  • ACM学习历程—HDU 5534 Partial Tree(动态规划)

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

    题目大意是给了n个结点,让后让构成一个树,假设每个节点的度为r1, r2, ...rn,求f(x1)+f(x2)+...+f(xn)的最大值。

    首先由于是树,所以有n-1条边,然后每条边连接两个节点,所以总的度数应该为2(n-1)

    此外每个结点至少应该有一个度。

    所以r1+r2+...rn = 2n-2ri >= 1;

    首先想到让ri >= 1这个条件消失:

    xi = ri,则x1+x2+...xn = n-2

    然后把所有f的脚标减一。即新f(i) = f(i+1)

    这样就相当于总和一定,求新f的和的最大值。而且与x的大小顺序无关。

    但是到这里利用p(i) = max(p(i), p(i-j)+f(j))的话,需要遍历选取次数、ij。这个复杂度应该是n^2(n-1)/2,是n^3级别的复杂度。

    考虑到0取和不取,虽然不影响i的大小,但是会影响p(i)的大小,而且一个数取了一个0之后,就会少一个数。

    于是又有一个消除0的条件:

    f(i) = f(i)-f(0),这样取0的贡献就是0,但是其他值的贡献是与f(0)的差值。

    那么最后答案加上原f(0)*n即可。

    然后就发现没了0的贡献后,其他值都随便取,而且不会超过n个数。

    然后就类似于完全背包一样,利用p(i) = max(p(i), p(i-j)+f(j))即可。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #define LL long long
    
    using namespace std;
    
    const int maxN = 2050;
    int n, f[maxN], p[maxN], ans;
    
    void input()
    {
        scanf("%d", &n);
        scanf("%d", &f[0]);
        for (int i = 1; i < n-1; ++i)
        {
            scanf("%d", &f[i]);
            f[i] -= f[0];
        }
        ans = f[0]*n;
        f[0] = 0;
        memset(p, -1, sizeof(p));
        p[0] = 0;
    }
    
    int myMax(int x, int y)
    {
        if (x == -1) return y;
        else return max(x, y);
    }
    
    void work()
    {
        for (int i = 0; i <= n-2; ++i)
            for (int j = i; j <= n-2; ++j)
                p[j] = myMax(p[j], p[j-i]+f[i]);
        ans += p[n-2];
        printf("%d
    ", ans);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        int T;
        scanf("%d", &T);
        for (int times = 0; times < T; ++times)
        {
            input();
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    称重量
    计算机网络
    进程间的通信方式与区别
    求两IP是否在同一局域网(运子网掩码用)
    Linux Redhat7 磁盘阵列基本原理
    Linux Redhat7更改root用户密码
    更改Linuxshell类型
    linux系统下的/var/spool/mail/root
    centos 解决"不在 sudoers 文件中。此事将被报告
    redhat 7 安装图形界面
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4965009.html
Copyright © 2011-2022 走看看