混合三種揹包問題

混合三種揹包問題

問題:

如果將 01揹包問題、完全揹包問題、多重揹包問題混合起來。也就是說,有的物品只可以取一次(01揹包),有的物品可以取無限次(完全揹包),有的物品可以取的次數有一個上限(多重揹包)。應該怎麼求解呢?

 

一、揹包與完全揹包的混合

考慮到在 01揹包問題 和 完全揹包問題 中給出的僞代碼只有一處不同,故如果只有兩類物品:一類物品只能取一次,另一類物品可以取無限次,那麼只需在對每個物品應用轉移方程時,根據物品的類別選用順序或逆序的循環即可,複雜度是O(VN)。僞代碼如下:

for i=1..N

    if 第i件物品是01揹包

        for v=V..0

            f[v]=max{f[v],f[v-c[i]]+w[i]};

    else if 第i件物品是完全揹包

        for v=0..V

            f[v]=max{f[v],f[v-c[i]]+w[i]};

 

例題:

旅行者有一個容量爲V公斤的揹包
n :物品種數
w :物品重量
v :物品價值
p :0表示可取無窮多件,1表示可取一件

求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

輸入樣例:
10 3
2 1 0
3 3 1
4 5 0
輸出樣例:
11
 

#include<cstdio>
#include<iostream>
 
using namespace std;
int V,n;
int w[31],v[31],p[31];
int f[201];
int max(int x,int y)
{
    if(x<y)return y;
    else return x;
}
int main(){
    scanf("%d%d",&V,&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&w[i],&v[i],&p[i]);
 
    for(int i=1;i<=n;i++){
        if(p[i]==0)     //完全揹包
        {
            for(int j=w[i];j<=V;j++)
                f[j]=max(f[j],f[j-w[i]]+v[i]);
        }
        else            //01揹包
        {
            for(int j=V;j>=w[i];j--)
                f[j]=max(f[j],f[j-w[i]]+v[i]);
        }
    }
    printf("%d",f[V]);
    return 0;
}

 

二、再加上多重揹包

 

如果再加上有的物品最多可以取有限次,那麼可以用 多重揹包問題中 將每個這類物品分成 個 01揹包的物品的方法。

當然,更清晰的寫法是調用我們前面給出的三個相關過程。

for i=1..N

    if 第i件物品是01揹包

        ZeroOnePack(c[i],w[i])  //調用01揹包問題函數

    else if 第i件物品是完全揹包

        CompletePack(c[i],w[i])  //調用完全揹包問題函數

    else if 第i件物品是多重揹包

        MultiplePack(c[i],w[i],n[i])  //調用多重揹包問題函數

 

例題:

旅行者有一個容量爲V公斤的揹包
n :物品種數
w :物品重量
v :物品價值
p :物品可以拿取的數目(0表示可取無窮多件)

求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

輸入樣例:
10 3
2 1 0
3 3 1
4 5 4
輸出樣例:
11
 

#include<cstdio>
#include<iostream>
 
using namespace std;
int V,n;
int w[31],v[31],p[31];
int f[201];
int max(int x,int y)
{
    if(x<y)return y;
    else return x;
}
int main(){
    scanf("%d%d",&V,&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&w[i],&v[i],&p[i]);
 
    for(int i=1;i<=n;i++){
        if(p[i]==0)     //完全揹包
        {
            for(int j=w[i];j<=V;j++)
                f[j]=max(f[j],f[j-w[i]]+v[i]);
        }
        else
        {
            for(int j=1;j<=p[i];j++)     //01揹包和多重揹包
                for(int k=V;k>=w[i];k--)
                    f[k]=max(f[k],f[k-w[i]]+v[i]);
        }
    }
    printf("%d",f[V]);
    return 0;
}

 

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