[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
Fudan Local Programming Contest 2012


题意为:

有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 
#include 
#include 
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>n)
    {
        sum=0;
        for(int i=1;i<=n;i++)
        {
            cin>>num[i];
            sum+=num[i];
        }
        cout<<"Case "<



你可能感兴趣的:([ACM]_组合数学,ACM题目,[ACM]_动态规划,ACM之路)