擺花(2012Noip普及組第3題)


擺花

(flower.cpp/c/pas)

【問題描述】

    小明的花店新開張,為了吸引顧客,他想在花店的門口擺上一排花,共 m 盆。通過調查顧客的喜好,小明列出了顧客最喜歡的 n 種花,從 1 到 n 標號。為了在門口展出更多種花,規定第 i 種花不能超過 ai盆,擺花時同一種花放在一起,且不同種類的花需按標號的從小到大的順序依次擺列。

    試編程計算,一共有多少種不同的擺花方案。

 

【輸入】

輸入文件 flower.in,共 2 行。

第一行包含兩個正整數 n 和 m,中間用一個空格隔開。

第二行有 n 個整數,每兩個整數之間用一個空格隔開,依次表示 a1、a2、……an

 

【輸出】

輸出文件名為 flower.out。

輸出只有一行,一個整數,表示有多少種方案。注意:因為方案數可能很多,請輸出方案數對 1000007 取模的結果。

 

【輸入輸出樣例 1】

flower.in

2 4

3 2

flower.out

2

分析:

動態規划:

題目要求花必須按從小到大的順序擺放,並且同種類的花必須挨着放,則題目就簡單多了

a[i]表示第i種花最多使用的盆數
f[i][j]表示前i種花,擺j盆的擺放方案數。對於第i種花可以使用0、1、2...a[i]盆,對應的前i-1種花擺放的盆數為j-0、j-1、j-2、...j-a[i]
即f[i][j]=f[i-1][j]+f[i-1][j-1]+f[i-1][j-2]+...+f[i-1][j-a[i]] =f[i-1][j-k](0<=k<=a[i],j>=k)
方程寫出來后,最關鍵的就是賦初始值

初始值f[1][0]=1,f[1][1]=1,...f[1][a[1]]=1;
初始值f[i][0]=1;(1<=i<=n)

2 4
3 2
 為例:
很顯然f[1][1]=f[1][2]=f[1][3]=1;
f[2][1]=2,前2種花,放一盆,則有1,2兩種方法。又
f[2][1]=f[1][0]+f[1][1]=f[1][0]+1可以推出f[1][0]=1;
同樣的方法可以推出f[2][0]=f[3][0]=...=f[n][0]=1;
(f[2][2]=f[1][0]+f[1][1]+f[1][2]
f[2][3]=f[1][1]+f[1][2]+f[1][3]
f[2][4]=f[1][2]+f[1][3]+f[1][2])
 
#include<iostream>
#include<cstring>
using namespace std;
int f[200][200]={{0,0}};
int a[200];
int main(){
 int n,m;
 cin>>n>>m;
 for(int i=1;i<=n;i++) cin>>a[i];
 memset(f,0,sizeof(f));
 for(int i=0;i<=a[1];i++) f[1][i]=1;
 for(int i=1;i<=n;i++)f[i][0]=1;
 for (int i=2;i<=n;i++)
  for(int j=1;j<=m;j++)
   for(int k=0;k<=a[i];k++)
    if (j>=k)f[i][j]=(f[i][j]+f[i-1][j-k])% 1000007;
 cout<<f[n][m]<<endl;
 return 0; 
}
View Code

 

 方法2:初始值f[0][0]=1;前0種花擺放0盆的方案數為1

//題目要求花必須按從小到大的順序擺放,並且同種類的花必須挨着放,則題目就簡單多了 
//f[i][j]表示前i種花,擺j盆的擺放方案數。對於第i種花可以使用0、1、2...a[i]盆,對應的前i-1種花擺放的盆數為j-0、j-1、j-2、...j-a[i] 
//即f[i][j]=f[i-1][j]+f[i-1][j-1]+f[i-1][j-2]+...+f[i-1][j-a[i]] (j>a[i])
//初始值f[0][0]=1;前0種花擺放0盆的方案數為1 
//方程寫出來后,最關鍵的就是賦初始值 
#include<iostream>
#include<cstring>
using namespace std;
int f[200][200]={{0,0}};
int a[200];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    memset(f,0,sizeof(f));
    f[0][0]=1;
//    for(int i=0;i<=a[1];i++) f[1][i]=1;
//    for(int i=1;i<=n;i++)f[i][0]=1;
    for (int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=a[i];k++)
                if (j>=k)f[i][j]=(f[i][j]+f[i-1][j-k])% 1000007;
    cout<<f[n][m]<<endl;
    return 0;    
}
View Code

 

       
       

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM