• [ACM] hdu 4248 A Famous Stone Collector (DP+组合)


    A Famous Stone Collector



    Problem Description
    Mr. B loves to play with colorful stones. There are n colors of stones in his collection. Two stones with the same color are indistinguishable. Mr. B would like to 
    select some stones and arrange them in line to form a beautiful pattern. After several arrangements he finds it very hard for him to enumerate all the patterns. So he asks you to write a program to count the number of different possible patterns. Two patterns are considered different, if and only if they have different number of stones or have different colors on at least one position.
     

    Input
    Each test case starts with a line containing an integer n indicating the kinds of stones Mr. B have. Following this is a line containing n integers - the number of 
    available stones of each color respectively. All the input numbers will be nonnegative and no more than 100.
     

    Output
    For each test case, display a single line containing the case number and the number of different patterns Mr. B can make with these stones, modulo 1,000,000,007, 
    which is a prime number.
     

    Sample Input
    3 1 1 1 2 1 2
     

    Sample Output
    Case 1: 15 Case 2: 8
    Hint
    In the first case, suppose the colors of the stones Mr. B has are B, G and M, the different patterns Mr. B can form are: B; G; M; BG; BM; GM; GB; MB; MG; BGM; BMG; GBM; GMB; MBG; MGB.
     

    Source


    题意为:

    有n种颜色的石头,每种颜色有num[i]块,每种颜色的石头是不可区分的,在这么多石头里面挑选石头来排成一条线,问一共同拥有多少种排法。线的长度为(1到  num[i]+num[2]+num[3]+.....num[n]。

    比方有三种颜色石头,B,G,M,表示颜色。每种颜色一块石头,那么可能的序列有 B; G; M; BG; BM; GM; GB; MB; MG; BGM; BMG; GBM; GMB; MBG; MGB

    用dp[i][j]代表用前i种颜色的石头去排成长度为j的序列

    那么有那种情况:

    ①第i种颜色的石头不使用,那么 dp[i][j] = dp[i-1][j];

    ②第i种颜色的石头使用(序列可到达长度为原来的长度加上第i种颜色的个数),有num[i]个。原来的石头序列中去掉k个,从第i种颜色石头中取出k个。这里(k<=j),插入到原来的序列中,一共同拥有j个位置,从中挑选k个就能够了(不是单纯的插空。能够理解为,要构成长度j的序列,有j个位置,首先让第i种颜色的k个石头去挑k个位置。这就包含了相邻和不相邻的情况,因为同样颜色不可区分,有 c[j][k]种方法,然后再让剩下的石头序列依照原来的顺序依次填入每一个空位置就能够了).

    有dp[i][j]+=dp[i-1][j-k]*c[j][k];

    代码:

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    typedef long long ll;
    const int maxn=110;//种类数最大
    const int mod=1000000007;
    ll dp[maxn][maxn*maxn];//代表用前i种颜色组成长度为j的序列的方法数
    ll c[maxn*maxn][maxn];//从当前序列长度+1种中选出j种。j不会超过maxn
    int n;//n种颜色
    int num[maxn];//每种颜色有多少石头
    int sum;//最长的序列长度
    
    void getC()
    {
        c[0][0]=c[1][0]=c[1][1]=1;
        for(int i=2;i<maxn*maxn-1;i++)
        {
            c[i][0]=1;
            for(int j=1;j<maxn-1;j++)
            {
                if(i==j)
                    c[i][j]=1;
                else
                {
                    c[i][j]=c[i-1][j]+c[i-1][j-1];
                    c[i][j]%=mod;
                }
            }
        }
    }
    
    int DP()
    {
        memset(dp,0,sizeof(dp));//一定的初始化为0。后面dp[i][j]=dp[i-1][j]用到了..
        for(int i=1;i<=n;i++)
            dp[i][0]=1;
        for(int i=1;i<=num[1];i++)
            dp[1][i]=1;
        int tsum=num[1];
        for(int i=2;i<=n;i++)//一共同拥有N种
        {
            tsum+=num[i];//前i种颜色的总长度,最多的
            for(int j=1;j<=tsum;j++)
            {
                dp[i][j]=dp[i-1][j];//对于当前长度j,一种情况是不用第i种颜色的石头
                for(int k=1;k<=num[i]&&k<=j;k++)//使用当前颜色石头,可是要去掉一定的长度,使用新的颜色石头来填充
                {
                    dp[i][j]+=dp[i-1][j-k]*c[j][k];//为什么是 c[j][k]呢,能够这样理解。一共同拥有J个位置。让第i中颜色的求先去选当中k个位置。然后剩下的位置让原来颜色的顺序放下就好了
                    dp[i][j]%=mod;
                }
            }
        }
        ll ans=0;
        for(int i=1;i<=sum;i++)
        {
            ans+=dp[n][i];
            ans%=mod;
        }
        return ans;
    }
    
    int main()
    {
        getC();
        int cas=1;
        while(cin>>n)
        {
            sum=0;
            for(int i=1;i<=n;i++)
            {
                cin>>num[i];
                sum+=num[i];
            }
            cout<<"Case "<<cas++<<": "<<DP()<<endl;
        }
        return 0;
    }
    



  • 相关阅读:
    005.python-anaconda报错没有pymysql .pip install 安装 jupyter仍然报错
    018.hive-hive两个表leftjoin,由于关联字段类型不同导致的数据错误(bigint、string)
    031.mysql-mysql 不等于会过滤null值问题,解决办法IFNULL(B1,'') != 1
    理解JavaScript的执行机制
    H5页面调app方法
    记录video 开发中遇到的问题
    i++ 与 ++i的区别
    text-align: justify
    请教一个问题:关于 webrtc 通信的问题
    模拟video播放器
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6924359.html
Copyright © 2020-2023  润新知