Luogu P1077 摆花

 P1077 摆花

题目描述

小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。

试编程计算,一共有多少种不同的摆花方案。

输入输出格式

输入格式:

 

第一行包含两个正整数n和m,中间用一个空格隔开。

第二行有n个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、……an。

 

输出格式:

 

输出只有一行,一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对1000007取模的结果。

 

输入输出样例

输入样例#1:
2 4
3 2
输出样例#1:
2

说明

【数据范围】

对于20%数据,有0<n≤8,0<m≤8,0≤ai≤8;

对于50%数据,有0<n≤20,0<m≤20,0≤ai≤20;

对于100%数据,有0<n≤100,0<m≤100,0≤ai≤100。

NOIP 2012 普及组 第三题

 

 

  简简单单的一道dp水题,转移方程找半天,我怕不是得退役。

  解1: dp[i][j]表示前i个品种,当摆放了j个花的时候的方案数。

  转移方程dp[i][j] = sum(dp[i-1][j-0],dp[i-1][j-1],…,dp[i-1][j-k]);  // k<=a[i]   想想这里为什么是j-k

  边界条件是dp[1..n][0] = 1;  意思是前i个品种摆放0个花时,方案数只有1.

  接下来是代码:

 1 #include <cstdio>
 2 
 3 int n, m, a[105];
 4 long long dp[105][105];
 5 
 6 
 7 int main()
 8 {
 9     //freopen("1.in", "r", stdin);
10     //freopen("1.out", "w", stdout);
11     
12     scanf("%d%d", &n, &m);
13     for(int i=1; i<=n; i++)
14         scanf("%d", &a[i]);
15     
16     for(int i=0; i<n; i++)
17         dp[i][0] = 1;
18     
19     for(int i=1; i<=n; i++)
20         for(int j=1; j<=m; j++)
21             for(int k=0; k<=a[i] && k<=j; k++)
22             {
23                 //k表示当前品种摆放数目
24                 dp[i][j] += dp[i-1][j-k];
25                 dp[i][j] %= 1000007;
26             }
27     /*
28     for(int i=0; i<=n; i++)
29     {
30         for(int j=0; j<=m; j++)
31             printf("(%d,%d)%lld ", i, j, dp[i][j]);
32         printf("\n");
33     }*/
34     printf("%lld", dp[n][m]);
35     return 0;
36 }

 

  解2:dp[i][j]表示前i个品种,还有j个空位的时候的方案数。

  转移方程dp[i][j] = sum(dp[i-1][j+0],dp[i-1][j+1],…,dp[i-1][j+k]);  // k<=a[i]  这里为什么是j+k

  边界条件是dp[1..n][m] = 1;  意思是前i个品种还有m个空位(摆放0个花)时,方案数只有1.

  

#include <cstdio>

int n, m, a[105];
long long dp[105][105];


int main()
{
    //freopen("1.in", "r", stdin);
    //freopen("1.out", "w", stdout);
    
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++)
        scanf("%d", &a[i]);
    
    for(int i=0; i<n; i++)
        dp[i][m] = 1;
    
    for(int i=1; i<=n; i++)
        for(int j=m-1; j>=0; j--)
            for(int k=0; k<=a[i] && k+j<=m; k++)
            {
                //k表示当前品种摆放数目
                dp[i][j] += dp[i-1][j+k];
                dp[i][j] %= 1000007;
            }
    /*
    for(int i=0; i<=n; i++)
    {
        for(int j=0; j<=m; j++)
            printf("(%d,%d)%lld ", i, j, dp[i][j]);
        printf("\n");
    }*/
    printf("%lld", dp[n][0]);
    return 0;
}

 

怕是要退役。。。

posted @ 2017-10-28 01:25  yBaka  阅读(193)  评论(0编辑  收藏  举报