揹包問題 01揹包 P1049 裝箱問題

2021-10-04 22:34:49 字數 1717 閱讀 5111

p1049 裝箱問題

f[i][j]: 把前面 i 件物品放進容量為 j 的揹包當中所獲得的最大價值

現在有 n 件物品,揹包容積為 v

那麼列出狀態轉移方程:

f[i][j]

= max(f[i-1][j], f[i-1][j-v[i]] + w[i]) , j > v[i]

= f[i-1][j] , j <= v[i]

= 0 , i = 0 or j = 0 //全域性陣列建立的時候預設為 0,可省略

其實就是對任意乙個物品 i 而言,要不要放進揹包的問題,如果不要,最大價值是 f[i-1][j],否則,可以創造f[i-1][j-v[i]] + w[i] 的最大價值

#include

//萬能標頭檔案

using

namespace std;

#define maxn 20005

int f[maxn]

[maxn]

, s[maxn]

,//時間, 即空間 space

v[maxn]

;//價值 value

intmain()

for(i =

1; i <= n; i++)}

}printf

("%d"

, v - f[n]

[v])

;return0;

}

主要是把一般的二維轉化成一維度的問題。

我想到有2種方式:

(1):令f[j] = f[n-1][j], 之前有 f[i][j] = max(f[i-1][j], f[i-1][j-v[i]] + w[i]) , j > v[i],因為f[i][j] >= f[i-1][j],可以多選擇乙個物品時的最大價值一定不會低,那麼 f[j] = f[n-1][j] >= f[i-1][j] , n >= i ,好了原式可化為

f[j] = max(f[j], f[j-v[i]] + w[i])

還要注意一點,要反著算,因為這樣的話,在推 f[p] 的時候就有 f[p-v[i]] = f[i-1][p-v[i]],算到這一層(i)的時候 i = 0, 1, … i-1 已經跑完了,不錯的,f[p-v[i]]剛好儲存了我想要的資料,要是還按照原來的順序的話,這個時候 f[p-v[i]] 就已經被更新過了,是f[i][p-v[i]] 不是我們需要的,錯誤。

(2):用人話來說原來的狀態轉移方程是在考慮要不要放物品 i 的問題,也就是說,和上面乙個狀態在比較,假如把第一維去掉,是沒有影響的(i、i-1 就代表了當前狀態和上乙個狀態,陣列的歷史陣列自然儲存了下來)(這是某位大佬同學告訴我的,偷偷告訴你,他高中就學會了)

#include

//萬能標頭檔案

using

namespace std;

#define n 1000000

int v[

105]

, s[

105]

;//v[i]: 第i件物品的價值, s[i]:第i件物品的體積

//這裡價值即為體積

int f[n]

;//只需要一維陣列就好了 f[j] = f[n-1][j]

intmain()

for(i =

1; i <= n; i++)}

printf

("%d"

, v-f[v]);

return0;

}

P1049 裝箱問題(01揹包)

題目描述 有乙個箱子容量為vv 正整數,0 le v le 200000 v 20000 同時有nn個物品 0要求nn個物品中,任取若干個裝入箱內,使箱子的剩餘空間為最小。輸入輸出格式 輸入格式 11個整數,表示箱子容量 11個整數,表示有nn個物品 接下來nn行,分別表示這nn個物品的各自體積 輸...

P1049 裝箱問題(01揹包)

題意 給你乙個揹包和一些物品,求把一些物品放進揹包中,揹包最少會空餘多少空間。思路 我們回想01揹包,就是在揹包容量內獲得最大價值,我們把每個物品的體積看做價值,也就轉化成了求揹包容量內的最大裝包量,然後進行01揹包,看最後f m 和m的差值即可。include define endl n defi...

P1049 裝箱問題(揹包)

有乙個箱子容量為vv 正整數,0 le v le 200000 v 20000 同時有nn個物品 00要求nn個物品中,任取若干個裝入箱內,使箱子的剩餘空間為最小。11個整數,表示箱子容量 11個整數,表示有nn個物品 接下來nn行,分別表示這nn個物品的各自體積 11個整數,表示箱子剩餘空間。in...