小明的花店新開張,爲了吸引顧客,他想在花店的門口擺上一排花,共m盆。經過調查顧客的喜愛,小明列出了顧客最喜歡的n種花,從1到n標號。爲了在門口展出更多種花,規定第i種花不能超過ai盆,擺花時同一種花放在一塊兒,且不一樣種類的花需按標號的從小到大的順序依次擺列。html
試編程計算,一共有多少種不一樣的擺花方案。ios
輸入共2行。算法
第一行包含兩個正整數n和m,中間用一個空格隔開。編程
第二行有n個整數,每兩個整數之間用一個空格隔開,依次表示a一、a二、……an。ide
輸出只有一行,一個整數,表示有多少種方案。注意:由於方案數可能不少,請輸出方案數對1000007取模的結果。spa
2 43d
3 2 code
2 htm
【輸入輸出樣例說明】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)
以題目的輸入樣例爲例子手動推演以下:
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 }
方法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 }
第二個方法的代碼每太搞懂。。。