2012年NOIP普及組 擺花

題目描述  Description

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

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

輸入描述  Input Description

輸入共2行。算法

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

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

輸出描述  Output Description

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

樣例輸入  Sample Input

2 43d

3 2 code

樣例輸出  Sample Output

htm

數據範圍及提示  Data Size & Hint

【輸入輸出樣例說明】blog

有2種擺花的方案,分別是(1,1,1,2),(1,1,2,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。

算法分析

動態規劃  (本文來自http://www.javashuo.com/article/p-rkweilqe-eo.html

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

a[i]表示第i種花最多使用的盆數
f[i][j]表示前i種花,擺j盆的擺放方案數。

對於第i種花能夠使用0、一、2...a[i]盆,對應的前i-1種花擺放的盆數爲j-0、j-一、j-二、...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])

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 int f[200][200]={{0,0}};
 6 int a[200];
 7 int main()
 8 {
 9     int n,m;
10     cin>>n>>m;
11     for(int i=1;i<=n;i++) cin>>a[i];
12     memset(f,0,sizeof(f));
13     
14     for(int i=0;i<=a[1];i++) f[1][i]=1;
15     for(int i=1;i<=n;i++) f[i][0]=1;
16     
17     for (int i=2;i<=n;i++)
18         for(int j=1;j<=m;j++)
19             for(int k=0;k<=a[i];k++)
20                 if(j>=k) f[i][j]=(f[i][j]+f[i-1][j-k])% 1000007;
21      cout<<f[n][m]<<endl;
22     return 0; 
23 }
View Code

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

 1 //題目要求花必須按從小到大的順序擺放,而且同種類的花必須挨着放,則題目就簡單多了 
 2 //f[i][j]表示前i種花,擺j盆的擺放方案數。對於第i種花能夠使用0、一、2...a[i]盆,對應的前i-1種花擺放的盆數爲j-0、j-一、j-二、...j-a[i] 
 3 //即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])
 4 //初始值f[0][0]=1;前0種花擺放0盆的方案數爲1 
 5 //方程寫出來後,最關鍵的就是賦初始值 
 6 #include<iostream>
 7 #include<cstring>
 8 using namespace std;
 9 int f[200][200]={{0,0}};
10 int a[200];
11 int main(){
12     int n,m;
13     cin>>n>>m;
14     for(int i=1;i<=n;i++) cin>>a[i];
15     memset(f,0,sizeof(f));
16     f[0][0]=1;
17 //    for(int i=0;i<=a[1];i++) f[1][i]=1;
18 //    for(int i=1;i<=n;i++)f[i][0]=1;
19     for (int i=1;i<=n;i++)
20         for(int j=0;j<=m;j++)
21             for(int k=0;k<=a[i];k++)
22                 if (j>=k)f[i][j]=(f[i][j]+f[i-1][j-k])% 1000007;
23     cout<<f[n][m]<<endl;
24     return 0;    
25 }
View Code

第二個方法的代碼每太搞懂。。。

相關文章
相關標籤/搜索