演算法1
(單調佇列優化) o(nv)
一共是n類物品,揹包的容量是m
每類物品的體積為v, 價值為w,個數為s
我們先來回顧一下傳統的dp方程
dp[i][j] 表示將前 i 種物品放入容量為 j 的揹包中所得到的最大價值
dp[i][j] = max(不放入物品 i,放入1個物品 i,放入2個物品 i, ... , 放入k個物品 i)
這裡 k 要滿足:k <= s, j - k*v >= 0
不放物品 i = dp[i-1][j]
放k個物品 i = dp[i-1][j - k*v] + k*w
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v] + w, dp[i-1][j-2*v] + 2*w,..., dp[i-1][j-k*v] + k*w)
實際上我們並不需要二維的dp陣列,適當的調整迴圈條件,我們可以重複利用dp陣列來儲存上一輪的資訊
我們令 dp[j] 表示容量為j的情況下,獲得的最大價值
那麼,針對每一類物品 i ,我們都更新一下 dp[m] --> dp[0] 的值,最後 dp[m] 就是乙個全域性最優值
dp[m] = max(dp[m], dp[m-v] + w, dp[m-2*v] + 2*w, dp[m-3*v] + 3*w, ...)
接下來,我們把 dp[0] --> dp[m] 寫成下面這種形式
dp[0], dp[v], dp[2*v], dp[3*v], ... , dp[k*v]
dp[1], dp[v+1], dp[2*v+1], dp[3*v+1], ... , dp[k*v+1]
dp[2], dp[v+2], dp[2*v+2], dp[3*v+2], ... , dp[k*v+2]
...dp[j], dp[v+j], dp[2*v+j], dp[3*v+j], ... , dp[k*v+j]
顯而易見,m 一定等於 kv + j,其中 0 <= j < v
所以,我們可以把 dp 陣列分成 j 個類,每一類中的值,都是在同類之間轉換得到的
也就是說,dp[kv+j] 只依賴於
因為我們需要的是中的最大值,
可以通過維護乙個單調佇列來得到結果。這樣的話,問題就變成了 j 個單調佇列的問題
所以,我們可以得到
dp[j] = dp[j]
dp[j+v] = max(dp[j] + w, dp[j+v])
dp[j+2v] = max(dp[j] + 2w, dp[j+v] + w, dp[j+2v])
dp[j+3v] = max(dp[j] + 3w, dp[j+v] + 2w, dp[j+2v] + w, dp[j+3v])
...
但是,這個佇列中前面的數,每次都會增加乙個 w ,所以我們需要做一些轉換
dp[j] = dp[j]
dp[j+v] = max(dp[j], dp[j+v] - w) + w
dp[j+2v] = max(dp[j], dp[j+v] - w, dp[j+2v] - 2w) + 2w
dp[j+3v] = max(dp[j], dp[j+v] - w, dp[j+2v] - 2w, dp[j+3v] - 3w) + 3w
...
這樣,每次入隊的值是dp[j+k*v] - k*w
單調佇列問題,最重要的兩點
1)維護佇列元素的個數,如果不能繼續入隊,彈出隊頭元素
2)維護佇列的單調性,即:尾值 >= dp[j + kv] - kw
本題中,佇列中元素的個數應該為 s+1 個,即 0 -- s 個物品 i
c++ **
#include #include using namespace std;
const int n = 20010;
int dp[n], pre[n], q[n];
int n, m;
int main() }}
cout << dp[m] << endl;
return 0;
}
揹包模型 多重揹包問題 III
有 nn 種物品和乙個容量是 vv 的揹包。第 ii 種物品最多有 sisi 件,每件體積是 vivi 價值是 wiwi 求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式第一行兩個整數,n,vn,v 0,0,用空格隔開,分別表示物品種數和揹包容積。接下來...
多維多重揹包問題 多重揹包問題
悼念512汶川大 遇難同胞 珍惜現在,感恩生活 急!災區的食物依然短缺!為了挽救災區同胞的生命,心繫災區同胞的你準備自己採購一些糧食支援災區,現在假設你一共有資金n元,而市場有m種大公尺,每種大公尺都是袋裝產品,其 不等,並且只能整袋購買。請問 你用有限的資金最多能採購多少公斤糧食呢?後記 人生是乙...
揹包問題 多重揹包
有n種物品和乙個容量為w的揹包。第i種物品最多有n i 件可用,每件重量是w i 價值是v i 求解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。1.使用三重迴圈進行遞推 狀態轉移式為 dp i j max 關鍵 如下 void solve printf d n dp n ...