二維費用的揹包問題

問題 
二維費用的揹包問題是指:對於每件物品,具有兩種不同的費用;選擇這件物品必須同時付出這兩種代價;對於每種代價都有一個可付出的最大值(例如:揹包容量)。問怎樣選擇物品可以得到最大的價值。設這兩種代價分別爲代價1和代價2,第i件物品所需的兩種代價分別爲a[i]和b[i]。兩種代價可付出的最大值(兩種揹包容量)分別爲V和U。物品的價值爲w[i]。

 

一、算法 


費用加了一維,只需狀態也加一維即可。設 f[i][v][u] 表示前 i 件物品付出兩種代價分別爲 v 和 u 時可獲得的最大價值。狀態轉移方程就是:

如前述方法,可以只使用二維的數組:當每件物品只可以取一次時變量v和u採用逆序的循環,當物品有如完全揹包問題時採用順序的循環。當物品有如多重揹包問題時拆分物品。

 

二、物品總個數的限制 


有時,“二維費用”的條件是以這樣一種隱含的方式給出的:最多隻能取M件物品。這事實上相當於每件物品多了一種“件數”的費用,每個物品的件數費用均爲1,可以付出的最大件數費用爲M。換句話說,設f[v][m]表示付出費用v、最多選m件時可得到的最大價值,則根據物品的類型(01、完全、多重)用不同的方法循環更新,最後在f[0..V][0..M]範圍內尋找答案。

另外,如果要求“恰取M件物品”,則在f[0..V][M]範圍內尋找答案。

 

三、複數域上的揹包問題

 

另一種看待二維揹包問題的思路是:將它看待成複數域上的揹包問題。

也就是說,揹包的容量以及每件物品的費用都是一個複數。而常見的一維揹包問題則是實數域上的揹包文圖。(注意:上面的話不嚴謹,因爲事實上只是我們處理的都是整數而已。)所以說,一維揹包的種種思想方法,往往可以應用於二維揹包問題的求解中,因爲只是數域擴大了而已。

 

 

四、例題

 

代碼:

#include <iostream>
#include <algorithm>
using namespace std;
#define N 105

int f[N][N];

int main() {
    int n,V,W; cin >> n >> V >>W;
    int v,m,w;
    for(int i = 0;i < n;i++) {
        scanf("%d%d%d",&v,&m,&w);
        for(int k = V;k >= v;k--) {
            for(int u = W;u >= m;u--) {
                f[k][u] = max(f[k][u],f[ k-v ][ u-m ] + w);
            }
        }
    }
    cout << f[V][W] << endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章