Knapsack problem

背包問題

大概的架構

一個有些規則的背包

放入一些東西找出"最好"的拿法

今天會說的

01背包

找零問題

01背包問題

一個背包大小為M的背包

要裝入n個物品(第i個物品的價值為Vi)

如何得到價值總和最大的物品

最直觀的想法

greedy算cp值?

假設有三個東西,背包總容量是6

mi=4, vi=5

mi=3, vi=3

mi=3, vi=3

那就不可行了

拿後兩個才能得到更大的價值

可以利用      (動態規劃)

開一個dp[n][m]的陣列紀錄

在拿了第i項時物品背包大小為j的價值

轉移式:dp [ i ][ j ] = max(dp [ i-1 ][ j-mi ] + vi, dp [ i-1 ] [ j ])

for(int i = 1; i <= n; i++) {
	int mi, vi;
	cin >> mi >> vi;
	for(int j = 0; j < mi; j++) {
		dp[i][j] = dp[i-1][j];
	}
	for(int j = mi; j <= m; j++) {
		dp[i][j] = max(dp[i-1][j], dp[i-1][j-m] + v); 
  	}
}
# PRESENTING CODE

範例

找零問題

找零問題的種類很多,在這裡以

"湊得某價位且使用最少硬幣"為例

有一個價格m

有n種錢幣,要湊到m

最少要使用幾個硬幣


其實跟剛剛的背包問題概念類似

轉移式:change[ i ][ j ] = min(change[ i-1 ][ j ], change[ i-1 ][ j-pi ] + 1]

for (int i = 0; i < n; i++)
        for (int j = price[i]; j <= m; j++)
            c[j] = min(c[j], c[j-price[i]] + 1);
# PRESENTING CODE

範例

Made with Slides.com