揹包問題(0/1揹包,完全揹包)

最經典的揹包問題莫過於是0/1揹包和完全揹包了。

1.0/1揹包

題目描述

一個旅行者有一個最多能用 m 公斤的揹包,現在有 n 件物品,它們的重量分別是 W1 ,W2 ,… , Wn ,它們的價值分別爲 C1,C2 ,… ,Cn 。若每種物品只有一件求旅行者能獲得最大總價值。

輸入格式

第 1 行:兩個整數,M(揹包容量,M≤200)和 N(物品數量,N≤30)。
第 2..N+1 行:每行二個整數 Wi,Ci,表示每個物品的重量和價值。

輸出格式

僅一行,一個數,表示最大總價值。

樣例數據

輸入
10 4
2 1
3 3
4 5
7 9

輸出
12

0/1揹包的特點就是每種物品只有一件,獨一無二,你只能選擇是裝這種物品,還是不裝這種物品。
用一個f[i][j]數組,表示前i件物品,總重量不超過j的最大價值。
若當前物品放入揹包,則 f[i][j]= f[i-1][j-w[i]]+c[i] ,即前i-1件物品的總價值加當前物品。
若物品不放入揹包,則前後總重量與總價值不變,僅i+1。
此時f[i][j]=f[i-1][j]
總方程 f[i][j]=max( f[i-1][j-w[i]]+c[i],f[i-1][j])

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;

int m,n;
int w[33],c[33],f[33][203];

int main()
{
    cin>>m>>n;
    for(int i=1;i<=n;i++)
        cin>>w[i]>>c[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(j>=w[i])
                f[i][j]=max(f[i-1][j-w[i]]+c[i],f[i-1][j]);
            else
                f[i][j]=f[i-1][j];
    cout<<f[n][m]<<endl;
    return 0;
}

2.完全揹包

題目描述

設有 n 種物品,每種物品有一個重量及一個價值。但每種物品的數量是無限的,同時有一個揹包,最大載重量爲 M ,今從 n 種物品中選取若干件(同一種物品可以多次選取),使其重量的和小於等於 M ,而價值的和爲最大。

輸入格式

第 1 行:兩個整數,M(揹包容量,M<=200)和 N(物品數量,N<=200)。
第 2..N+1 行:每行二個整數 Wi,Ci,表示每個物品的重量和價值。

輸出格式

僅一行,一個數,表示最大總價值。

樣例數據

輸入
12 4
2 1
3 3
4 5
7 9

輸出
15

完全揹包與0/1揹包的區別在於每種物品的個數是無限的,也就是說你可以拿任意多件的某種物品,而不是獨一無二。
因此狀態轉移方程也會有些許變化。
依舊用0/1揹包的思路。
用一個f[i][j]數組,表示前i件物品,總重量不超過j的最大價值。
若物品不放入揹包,則前後總重量與總價值不變,僅i+1,這與0/1揹包完全一樣
此時f[i][j]=f[i-1][j]
若物品放入揹包,由於每種物品可以取多件
f[i][j]=f[i][j-w[i]]+c[i]
總方程 f[i][j]=max(f[i][j-w[i]]+c[i],f[i-1][j])

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;

int m,n;
int w[210],c[210],f[210][210];

int main()
{
    cin>>m>>n;
    for(int i=1;i<=n;i++)
        cin>>w[i]>>c[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(j>=w[i])
                f[i][j]=max(f[i][j-w[i]]+c[i],f[i-1][j]);
            else
                f[i][j]=f[i-1][j];
    cout<<f[n][m]<<endl;
    return 0;
}

其實二者代碼差不多,只是狀態轉移方程有些許不同。

——我認爲return 0,是一個時代的終結。

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