zoukankan      html  css  js  c++  java
  • HDU 5534 Partial Tree

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

    题意:让你建立一个n个节点的树,同时给出一个节点有k度的价值 (1<=k<=n-1),问树最大的价值

    比较容易相到的dp方程为dp[i][j]表示选到第i个点总共选了j的度数的最大价值

    可惜这样是o(n3),会T

    我们可以这样优化,先给每个节点分配1个度数,那么问题就变成了把n-2度分配给n个点,这样就不需要考虑是否取到了n个点

    有2种做法

    第一种设dp[i][j]表示之前选的分配过的最大度数,j表示现在选取的总度数

    dp[i][j]=max(dp[i-1][j],dp[i][j-i]+a[i+1]-a[1])

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    int a[2050];
    int dp[2][2050];
    int now=0,pre=1;
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n;
            scanf("%d",&n);
            for(int i=1;i<n;i++)
                scanf("%d",&a[i]);
            memset(dp[now],0,sizeof(dp[now]));
            dp[now][0]=a[1]*n;
            for(int i=1;i<=n-2;i++)
            {
                swap(now,pre);
                memset(dp[now],0,sizeof(dp[now]));
                for(int j=0;j<i;j++) dp[now][j]=dp[pre][j];
                for(int j=i;j<=n-2;j++)
                    dp[now][j]=max(dp[pre][j],dp[now][j-i]+a[i+1]-a[1]);
            }
            printf("%d
    ",dp[now][n-2]);
        }
        return 0;
    }
    

    第二种则是考虑把它当作完全背包考虑

    但要注意应该初始化为负无穷

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    int a[2050];
    int dp[2050];
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n;
            scanf("%d",&n);
            for(int i=1;i<n;i++)
                scanf("%d",&a[i]);
            for(int i=0;i<=n;i++)
                dp[i]=-1e9;
            dp[0]=a[1]*n;
            for(int i=1;i<=n-2;i++)
                for(int j=i;j<=n-2;j++)
                    dp[j]=max(dp[j],dp[j-i]+a[i+1]-a[1]);
            printf("%d
    ",dp[n-2]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    linux 下安装nodejs,CentOS 6.5 系统
    nginx 做负载均衡
    windows 下安装nginx
    Markdown 添加空行 空格
    Latex 部分语法
    中国古代文学史——先秦(原始歌谣、神话、《诗经》、《尚书》、《春秋》、《国语》、《左传》、《战国策》、诸子散文、楚辞)
    图论学习笔记
    集合论学习笔记
    Office 365 Word 打开网上下载文件出现错误
    路径规划基础知识
  • 原文地址:https://www.cnblogs.com/bk-201/p/7574481.html
Copyright © 2011-2022 走看看