首页 > 其他 > 详细

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

时间:2014-07-30 17:41:44      阅读:375      评论:0      收藏:0      [点我收藏+]

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



[ACM] hdu 4248 A Famous Stone Collector (DP+组合),布布扣,bubuko.com

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

原文:http://blog.csdn.net/sr_19930829/article/details/38300709

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!