题目链接: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的方案数。
f[i][j]表示选到第i个人时,属性和为j的方案数
f[i][j] = Σf[i - 1][k] (0<=j - k <=t[i])
#include<cstdio>
#include<cstring>
#include<iostream>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int MOD = 1000000007;
const int N = 2010;
int a[N];
int f[N][N];
int n, sum;
void dp()
{
memset(f, 0, sizeof(f));
for (int i = 0; i <= a[1]; i++)
{
f[1][i] = 1;
}
for (int i = 2; i <= n; i++)
{
for (int j = 0; j <= sum; j++)
for (int k = 0; k <= a[i] && k <= j; k++)
{
f[i][j] = (f[i][j] + f[i - 1][j - k]) % MOD;
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n) ;
sum = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]) ;
sum += a[i] ;
}
dp();
printf("%d\n", f[n][sum / 2]);
}
return 0;
}