HDU 5000 Clone(背包dp)

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;
}


你可能感兴趣的:(背包DP)