擺花 dp,揹包,各種優化

2021-10-10 02:36:33 字數 2642 閱讀 3717

題目描述

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

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

輸入格式

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

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

輸出格式

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

輸入輸出樣例

輸入2 4

3 2輸出

2說明/提示

【資料範圍】

對於20%資料,有0對於50%資料,有0對於100%資料,有0我一開始想的是dp[i][j]表示已經擺了i盆花,最後擺的花種類為j的方案總數,則最後答案為dp[n][1...m](累加)(這裡定義的n為盆數,m為種數)

這樣的狀態很麻煩。

我們需要:

一層for遍歷擺的盆數 i

二層for遍歷結尾擺的種類 j

三層for遍歷 j 種類擺的盆數 k (k從1開始,不能從0開始,因為已經規定了最後種類為 j )

四層for遍歷 該種類在 l (1<=l<=j-1) 後面 (設j=4,可以考慮到前乙個種類是1,2,3

#include

#include

#include

#define ll long long

using

namespace std;

const

int mod =

1000007

;int

main()

}}} ll ans =0;

for(

int i =

1;i <= m;i++

) ans =

(ans+dp[n]

[i])

%mod;

printf

("%lld\n"

,ans)

;return0;

}

這種時間複雜度很高,但是樣例比較水還是ac了。我們試著優化一下。

我們發現第四層迴圈其實就是dp[i][j] + dp[i-k][1...j-1],這其實就是字首和。那麼我們可以定義sum[i][j]表示擺了i盆花,最後擺的花種類為[1…j]的的方案總數,則我們最終求得答案就是sum[n][m](n為個數,m為種類)

#include

#include

#include

#define ll long long

using

namespace std;

const

int mod =

1000007

;int

main()

sum[i]

[j]=

(sum[i]

[j-1

]+dp[i]

[j])

%mod;

//更新字首和 }}

printf

("%lld\n"

,sum[n]

[m])

;return0;

}

這樣優化後n,m取最大也能ac.

這種狀態寫起來是麻煩的。如果將狀態定義為:

dp[i][j]表示在前 n 種花,當前已有 j 盆的方案總數,那麼最後結果就是dp[n][m](n為種數,m為個數)

第一層for遍歷種類 i

第二層for遍歷個數 j ( j 從0開始,因為第一盆可以從2~n起始)

第三層for遍歷第 i 種選擇放的個數 k ( k 從0開始,設 i = 2, 可以考慮有 [1,3]這種情況)

dp[i][j] = (dp[i][j]+dp[i-1][j-k])%mod

#include

#include

#include

using

namespace std;

intmain()

}}printf

("%lld\n"

,dp[n]

[m])

;return0;

}

可以像01揹包一樣優化一下空間。

我們發現dp[i][j]的更新只和dp[i-1][x](x<=j)層有關係,這和01揹包的情況是一樣的,因此可以滾動陣列優化。

#include

#include

#include

using

namespace std;

intmain()

}}printf

("%lld\n"

,dp[m]);

return0;

}

P1077 擺花 揹包DP

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

擺花 01揹包

p1077 noip2012 普及組 擺花 洛谷 電腦科學教育新生態 luogu.com.cn 很很很基礎的一道01揹包問題,但是對目前的我來說還是有亮點的。狀態表示 前i種花共j盆的擺放方案數量 狀態計算 1.如果第i種花不擺 f i,j f i 1,j 2.如果第i種花擺 遍歷第i種花能擺放擺放...

洛谷P1077 擺花 揹包dp

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