POJ Ant Counting DP

本文介绍了一种使用动态规划解决特定组合问题的方法,并通过优化状态转移方程和利用前缀和来降低时间复杂度,最终实现了高效的算法解决方案。

dp[i][j]表示前i种蚂蚁组成元素个数为j的集合有多少种。

则dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + ... + dp[i-1][ max(0,j-a[i])];

直接算的话复杂度为O(TA^2)

状态的转移是一个区间内的数的和,所以再用一个数组f[i][j]记录dp[i][j]的前缀和。

dp[i][j] = f[i-1][j]-f[i-1][j-a[i]-1];

复杂度为O(TA)

同时可以用滚动数组优化空间复杂度。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;
const int maxn = 110005;
const int mod = 1000000;
int dp[maxn];
int da[1005];
int f[maxn];
int n,A,a,b;
int main()
{
    while( scanf("%d%d%d%d", &n, &A, &a, &b) != EOF)
    {
        memset(da,0,sizeof(da));
        for(int i = 1;i <= A; i++)
        {
            int x; scanf("%d", &x);
            da[x]++;
        }
        dp[0]=1;
        f[0]=1;
        int maxv=0;
        for(int i = 1; i <= n; i++)
        {
            maxv += da[i];
            for(int i=0;i<=maxv;i++)
                f[i]=(f[i-1]+dp[i])%mod;
            for(int j=1; j <= min(b,maxv); j++)
            {
                dp[j]=(f[j]-(j-da[i]<=0?0:f[j-da[i]-1]))%mod;
            }
        }
        int res=0;
        for(int i=a;i<=b;i++)
            res=(res+dp[i])%mod;
        printf("%d\n",res);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/BMan/p/3680709.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值