动态规划——Ant Counting(多重级组合数)

一、Ant Counting

Ant Counting POJ - 3046(中文翻译)
有一天,贝茜无聊地坐在蚂蚁洞前看蚂蚁们进进出出地搬运食物.很快贝茜发现有些蚂蚁长得几乎一模一样,于是她认为那些蚂蚁是兄弟,也就是说它们是同一个家族里的成员.她也发现整个蚂蚁群里有时只有一只出来觅食,有时是几只,有时干脆整个蚁群一起出来.这样一来,蚂蚁们出行觅食时的组队方案就有很多种.作为一头有数学头脑的奶牛,贝茜注意到整个蚂蚁群由T(1≤T≤1000)个家族组成,她将这些家族按1到T依次编号.编号为i的家族里有Ni(1≤Ni≤100)只蚂蚁.同一个家族里的蚂蚁可以认为是完全相同的.
如果一共有S,S+1….,B(1≤S≤B≤A)只蚂蚁一起出去觅食,它们一共能组成多少种不同的队伍呢?注意:只要两支队伍中所包含某个家族的蚂蚁数不同,我们就认为这两支队伍不同.由于贝茜无法分辨出同一家族的蚂蚁,所以当两支队伍中所包含的所有家族的蚂蚁数都相同时,即使有某个家族换了几只蚂蚁出来,贝茜也会因为看不出不同而把它们认为是同一支队伍.
3 sets with 1 ant: {1} {2} {3}
5 sets with 2 ants: {1,1} {1,2} {1,3} {2,2} {2,3}
5 sets with 3 ants: {1,1,2} {1,1,3} {1,2,2} {1,2,3} {2,2,3}
3 sets with 4 ants: {1,2,2,3} {1,1,2,2} {1,1,2,3}
1 set with 5 ants: {1,1,2,2,3}
求可以创建的大小为S…B(包括)的集合数。 像{1,2}这样的集合与集合{2,1}相同,不应重复计算。 仅打印此数字的最后六位数,不带前导零或空格。

输入:t(族群数)n(蚂蚁总数)S,B
输出:集合大小为s到b的组合数

二、题目分析

我们将同种的蚂蚁数数储存在一个数组f[i]里,表示第i种蚂蚁的数量

for(int i=0;i>ant[i];
        f[ant[i]]++;
    }

设定一个数组s[i][j]表示前i种蚂蚁,组成大小为j的集合的数量,动态转移方程:s[i][j]=s[i-1][j]+s[i-1][j-1]+……+s[i-1][j-f[i]];
意思是将前i种蚂蚁选j个蚂蚁的组合数等于在前i-1种选j-k个蚂蚁,剩下的k个蚂蚁从第i种选 ( 0<=k<=f[i])
当然空间可以优化s变为一维数组:
空间优化

#include
#include
using namespace std;
int main()
{
    int t,n,a,b;
    int f[1005]={0};
    int ant[100005];
    int s[100005]={0};
    int ans=1;
    cin>>t>>n>>a>>b;
    for(int i=0;i>ant[i];
        f[ant[i]]++;
    }
    int sum=0,lastsum=0;
    s[0]=1;
    for(int i=1;i<=t;i++)
    {
        sum+=f[i];
        for(int j=sum;j>=0;j--)
        {
            for(int k=j-1;k>=j-f[i];k--)
            {
                if(k>=0)
                s[j]=(s[j]+s[k]+1000000)%1000000;
            }
        }
    }
    lastsum=0;
    for(int i=a;i<=b;i++)
        lastsum=(lastsum+s[i]+1000000)%1000000;
    cout<

时间也可优化o(n2)
当j>f[i]时(j-1-f[i]>=0):
s[i][j]=s[i][j−1]+s[i−1][j]−s[i−1][j−fi−1];
当j<=f[i]时:
s[i][j] = s[i-1][j]+s[i][j-1]
动态规划——Ant Counting(多重级组合数)_第1张图片
动态规划——Ant Counting(多重级组合数)_第2张图片

你可能感兴趣的:(练习题目)