擺花(NOIP2012 普及組第三題)
阿新 • • 發佈:2017-10-01
數據規模 .cn ostream .com col tdi int png namespace 問題描述
小明的花店新開張,為了吸引顧客,他想在花店的門口擺上一排花,共m盆。通過調查顧客的喜好,小明列出了顧客最喜歡的n種花,從1到n標號。為了在門口展出更多種花,規定第i種花不能超過ai盆,擺花時同一種花放在一起,且不同種類的花需按標號的從小到大的順序依次擺列。
試編程計算,一共有多少種不同的擺花方案。 輸入格式 第一行包含兩個正整數n和m,中間用一個空格隔開。
第二行有n個整數,每兩個整數之間用一個空格隔開,依次表示a1、a2、……an。 輸出格式 輸出只有一行,一個整數,表示有多少種方案。註意:因為方案數可能很多,請輸出方案數對1000007取模的結果。 樣例輸入 2 4
3 2 樣例輸出
2
輸入輸出樣例說明
有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。
試編程計算,一共有多少種不同的擺花方案。 輸入格式 第一行包含兩個正整數n和m,中間用一個空格隔開。
第二行有n個整數,每兩個整數之間用一個空格隔開,依次表示a1、a2、……an。 輸出格式 輸出只有一行,一個整數,表示有多少種方案。註意:因為方案數可能很多,請輸出方案數對1000007取模的結果。 樣例輸入 2 4
3 2 樣例輸出
對於50%數據,有0<n≤20,0<m≤20,0≤ai≤20;
對於100%數據,有0<n≤100,0<m≤100,0≤ ai≤100。
分析
動態規劃:題目要求花必須按從小到大的順序擺放,並且同種類的花必須挨著放,則題目就簡單多了。
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> using namespace std; int n, m , a[120] = {0}, f[120][120] = {0}; const int mod = 1000007; int main() { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); cin >> n >> m; for(int i = 1;i <= n;i++) { cin >> a[i]; } f[0][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(k <= j) { f[i][j] = (f[i][j]+f[i-1][j-k])%mod; } } } } cout << f[n][m] << endl; return 0; }
擺花(NOIP2012 普及組第三題)