POJ 3046

题目大意:蚂蚁牙黑,蚂蚁牙红:有A只蚂蚁,来自T个家族,分别记为ant[i]个。同一个家族的蚂蚁长得一样,但是不同家族的蚂蚁牙齿颜色不同。任取n只蚂蚁(S <= n <= B),求能组成几种集合?

状态:dp[i][j]:前i种中选j个可以组成的种数

决策:第i种选k个,k<=ant[i] && j-k>=0

转移:dp[i][j]=Σdp[i-1][j-k]

复制代码
#include<stdio.h>
#include<string.h>
int dp[1005][10050];
int num[10050];
int main(){
    int n,m,a,b,x;
    while(scanf("%d%d%d%d",&n,&m,&a,&b)!=EOF){
        memset(num,0,sizeof(num));
        for(int i=0;i<m;i++){
            scanf("%d",&x);
            num[x]++;
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<=num[1];i++) dp[1][i]=1;
        for(int i=2;i<=n;i++){
            for(int j=0;j<=b;j++){
                for(int k=0;k<=num[i];k++){
                    if(j>=k) {
                    dp[i][j]+=dp[i-1][j-k];
                    dp[i][j]%=1000000;
                    }
                }
            }
        }
        int ans=0;
        for(int i=a;i<=b;i++){
            ans+=dp[n][i];
            ans%=1000000;
        }
        printf("%d\n",ans);
    }
    return 0;
}
复制代码

还有一种

dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-ant[i]-1]

复制代码
#include<iostream>
using namespace std;
#define MOD 1000000
int T, A, S, B;
int ant[1005];
int dp[2][100000];
int ans;
int main()
{
    scanf("%d%d%d%d", &T, &A, &S, &B);
    for (int i = 1; i <= A; i++)
    {
        int aa;
        scanf("%d", &aa);
        ant[aa]++;
    }
    dp[0][0] = dp[1][0] = 1;
    for (int i = 1; i <= T; i++)
        for (int j = 1; j <= B; j++)
            if (j - ant[i] - 1 >= 0) dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1] - dp[(i - 1) % 2][j - ant[i] - 1] + MOD) % MOD;      //在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数)
            else dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1]) % MOD;
    for (int i = S; i <= B; i++)
        ans = (ans + dp[T % 2][i]) % MOD;
    printf("%d\n", ans);
    return 0;
}
复制代码

猜你喜欢

转载自www.cnblogs.com/wpbing/p/9508743.html
今日推荐