http://acm.hdu.edu.cn/showproblem.php?pid=5000

题意:有n种属性,每种属性的数值可以是0-T[i],当一个人属性全部小于等于另一个人的属性时,小的那个人会被淘汰,问最多同时存在多少人

比赛的时候没有想到这题的关键点,没出来也是情理之中

解法:sum表示一个人的属性和。首先,人数最多的情况下这些人的sum是相同的,因为这种情况下一个属性减少另一个属性必然增加,保证满足条件。其次发现,sum=0的方案数和sum=ΣT[i]的方案数相同,因此在sum=(ΣT[i])/2取得最大值(没找到完整的推理,只是根据猜测。。)。这样问题转化为n个数,每个数可以取0-T[i],和为(ΣT[i])/2的方案数。

dp[i][j]表示选到第i个人时,属性和为j的种数

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std ;

const int mod=1000000007 ;

int T[2005],dp[2005][2005] ;

int main()
{
    int t ;
    scanf("%d",&t) ;
    while(t--)
    {
        int n ;
        scanf("%d",&n) ;
        int sum=0 ;
        for(int i=0 ;i<n ;i++)
        {
            scanf("%d",&T[i]) ;
            sum+=T[i] ;
        }
        memset(dp,0,sizeof(dp)) ;
        for(int i=0 ;i<=T[0] ;i++)
            dp[0][i]=1 ;
        sum>>=1 ;
        for(int i=1 ;i<n ;i++)
        {
            for(int j=0 ;j<=sum ;j++)
            {
                for(int k=0 ;k<=T[i] ;k++)
                {
                    if(j<k)break ;
                    dp[i][j]=(dp[i][j]+dp[i-1][j-k])%mod ;
                }
            }
        }
        printf("%d\n",dp[n-1][sum]) ;
    }
    return 0 ;
}
View Code