動態規劃之揹包九講之三 — 多重揹包

題目:有 N 種物品和一個容量是 V 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。

輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品種數和揹包容積。接下來有 N 行,每行三個整數 vi,wi,si,用空格隔開,分別表示第 i 種物品的體積、價值和數量。

輸出格式
輸出一個整數,表示最大價值。

數據範圍
0<N,V≤100
0<vi,wi,si≤100

解析:本題數據範圍較小,可以在O(n3)複雜度內解決。用多重揹包最初版本
Code:

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 110;
int f[N];
int main()
{
    int n,V;
    cin>>n>>V;
    for(int i=1;i<=n;i++)
    {
        int v,w,s;
        cin>>v>>w>>s;
        for(int j=V;j>=v;j--)
        {
            for(int k=1;k<=s && k*v<=j;k++)
            {
                f[j] = max(f[j],f[j-k*v]+k*w);
            }
        }
    }
    cout<<f[V];
    return 0;
}

多重揹包二進制優化版本
若本題數據範圍從100擴大至1000,則O(n3)會TLE,所以需要進行優化。
Code:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 2010;
int f[N];
struct Thing
{
    int v,w;
};
vector<Thing> things;
int main()
{
    int n,V;
    cin>>n>>V;
    for(int i=0;i<n;i++)
    {
        int v,w,s;
        cin>>v>>w>>s;
        for(int k=1;k<=s;k*=2)
        {
            s -= k;
            things.push_back({v*k,w*k});
        }
        if(s > 0)   things.push_back({s*v,s*w});
    }
    for(auto thing : things)
    {
        for(int j=V;j>=thing.v;j--)
        {
            f[j] = max(f[j],f[j-thing.v]+thing.w);
        }
    }
    cout<<f[V];
    return 0;
}

ps:博主能力有限,如果讀者發現什麼問題,歡迎私信或評論指出不足。歡迎讀者詢問問題,樂意盡我所能解答讀者的問題。歡迎評論,歡迎交流。謝謝大家!

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