zoukankan      html  css  js  c++  java
  • hdu5000 Clone dp+大数

    After eating food from Chernobyl, DRD got a super power: he could clone himself right now! He used this power for several times. He found out that this power was not as perfect as he wanted. For example, some of the cloned objects were tall, while some were short; some of them were fat, and some were thin. 

    More evidence showed that for two clones A and B, if A was no worse than B in all fields, then B could not survive. More specifically, DRD used a vector v to represent each of his clones. The vector v has n dimensions, representing a clone having N abilities. For the i-th dimension, v[i] is an integer between 0 and T[i], where 0 is the worst and T[i] is the best. For two clones A and B, whose corresponding vectors were p and q, if for 1 <= i <= N, p[i] >= q[i], then B could not survive. 

    Now, as DRD's friend, ATM wants to know how many clones can survive at most.

    题意:有许多克隆人,每个人都有 N 项属性,每个属性都有上限,每个克隆人的属性是 1 到 该属性上限的一个整数。现在如果有克隆人所有属性都小于等于另外某个克隆人,那么他就无法生存,问给定每个属性上限,最多有多少克隆人可以生存。

    N范围2000,所有属性上限的总和范围也是2000。

    其实最优的情况是所有克隆人属性总和都相等,那么一定有人在这个属性比较优,而其他的在另一个属性比较优,前提是没有两个人所有属性均相等。

    那么问题其实就变成了如果我知道属性总和,有多少种不同的构成这个总和的方法?然后对于所有总和都求一遍,取一个最大值就可以了。

    那么就变成了非常经典的DP思路,拆分数字。

    DP[ i ][ j ] 表示选取完第 i 个数,总和是 j 的情况总数;

    第 i 个数的取值范围是 1 ~ T[ i ],T[ i ] 是第 i 个属性的上限;

    枚举这个数的取值是 k ,DP[ i ][ j ] = ∑ ( k:1~T[i] ) ( DP[ i-1 ][ j-k ] );

    然后因为 j 是前一层中 j 较小的一部分的和,所以可以从后往前更新,压缩掉 i 这一维。

    用大数写。

     1 import java.util.*;
     2 import java.math.BigInteger;
     3 public class Main {
     4     static int t[]=new int[2005];
     5     static BigInteger dp[]=new BigInteger[2005];
     6     static BigInteger mmod = BigInteger.valueOf(1000000007);
     7     public static void main(String[] args){
     8         Scanner input = new Scanner(System.in);
     9         for(int i=1;i<=2000;++i){
    10             t[i]=0;
    11             dp[i]=BigInteger.ZERO;
    12         }
    13        int T=input.nextInt();
    14        while(T--!=0){
    15            int n=input.nextInt();
    16            int i=0,sum=0;
    17            for(i=1;i<=n;++i){
    18                t[i]=input.nextInt();
    19                sum+=t[i];
    20            }
    21            sum=sum*2/3;
    22            for(i=1;i<=2000;++i)dp[i]=BigInteger.ZERO;
    23            BigInteger mx=BigInteger.ZERO;
    24            dp[0]=BigInteger.ONE;
    25            for(i=1;i<=n;++i){
    26                for(int j=sum;j>0;--j){
    27                    for(int k=1;k<=t[i]&&j>=k;++k){
    28                        dp[j]=dp[j].add(dp[j-k]);
    29                    }
    30                }
    31            }
    32            for(i=1;i<=sum;++i){
    33                if(mx.compareTo(dp[i])<0)mx=dp[i];
    34            }
    35            mx=mx.mod(mmod);
    36            System.out.println(mx);
    37        }
    38        input.close();
    39     }
    40 }
    View Code
  • 相关阅读:
    第几天
    打印图形
    父类上的注解能被子类继承吗
    [LeetCode] 108. Convert Sorted Array to Binary Search Tree ☆(升序数组转换成一个平衡二叉树)
    探究高可用服务端架构的优秀资料索引
    无序数组的中位数
    [LeetCode] 113. Path Sum II ☆☆☆(二叉树所有路径和等于给定的数)
    [LeetCode] 112. Path Sum ☆(二叉树是否有一条路径的sum等于给定的数)
    翻转单词
    [LeetCode] 110. Balanced Binary Tree ☆(二叉树是否平衡)
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/6843639.html
Copyright © 2011-2022 走看看