Clone
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5000
解题思路:
题目大意:每个克隆人有n个属性,下面n个数字表示每个属性的值范围为[ 0, T[i] ],如果A的所有能力值比B低,那A不能存活。问:最多可以有多少人存活?
算法思想:
规律1:sum相同的克隆人不会互相杀死。
因为若2个克隆人的属性都相同,A克隆某个属性要增加1,则A克隆另一个属性要减少1,这样AB一定能共存。
规律2:
sum不同的克隆不会重合。
我们设A克隆sum = x,B克隆sum = y,若A,B克隆能共存,但不会把AB同时放到这个圈里。
因为一定存在一只克隆C ,sum = x,且C和B不能共存,既然不能共存,则我们放入C克隆是不会影响答案的。
所以dp[i][j]表示前i个克隆人sum 为 j 时的方案数。
但我们结果是要mod的,所以不能给所有sum取最大值。
可以发现sum = 0 和 sum = 求和(T[i]) 的方案数是一样的。
同理sum其实是对称的,和组合数一样。所以dp[n][求和(T[i]) / 2] 是最大的。
思路参考于九野的博客。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 2010;
const int MOD = 1e9+7;
int dp[N][N];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,sum = 0;
int t[N];
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%d",&t[i]);
sum += t[i];
}
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i = 0; i < n; i++)
for(int j = 0; j <= sum; j++)
for(int k = 0; k <= t[i]; k++)
dp[i+1][j+k] = (dp[i+1][j+k]+dp[i][j])%MOD;
printf("%d\n",dp[n][sum/2]);
}
return 0;
}