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...