背包模板——01背包、完全背包、多重背包

01背包

有n件物品和一个容量为v的背包。每种物品仅有一件,可以选择放或不放。

第i件物品的重量是weight[i],价值是value[i]。

求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=1e5+10;
int weight[MAX+50];
int value[MAX+50];
int dp[MAX+50];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        int n,v;
        cin>>n>>v;
        int i,j;
        for(i=1;i<=n;i++)
            cin>>weight[i]>>value[i];
        for(i=1;i<=n;i++)
        {
            for(j=v;j>=weight[i];j--)
            {
                dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
            }
        }
        cout<<dp[v]<<endl;
    }
}

完全背包

有n件物品和一个容量为v的背包。每种物品有无限件可以重复使用,可以选择放或不放。

第i件物品的重量是weight[i],价值是value[i]。

求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=1e5+10;
int weight[MAX+50];
int value[MAX+50];
int dp[MAX+50];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        int n,v;
        cin>>n>>v;
        int i,j;
        for(i=1;i<=n;i++)
            cin>>weight[i]>>value[i];
        for(i=1;i<=n;i++)
        {
            for(j=weight[i];j<=v;j++)//和0-1背包不同
            {
                dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
            }
        }
        cout<<dp[v]<<endl;
    }
}

多重背包

有m件物品和一个容量为v的背包。第i种物品最多有n[i]件可用,可以选择放或不放。

第i件物品的重量是weight[i],价值是value[i]。

求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

(多重背包问题其实从本质来讲就是对01背包和完全背包的灵活运用,对于那些数量*价值>总容量的元素,我们可以认为它对于背包来说是无限个的,因为怎么取都不可能把所有元素取完,那数量*价值<总容量的元素我们也可以经过灵活处理把它变成01背包问题,这里需要用到线性代数的极大线性无关组的思想,我们把数量拆成1.2.4.8……这样的,因为从二进制的角度讲由于1.2.4.8……这样的组合每一个数的二进制码都不会在同一位置重复,所以很明显这组数是可以组合出任何一组数的,所以我们就不用对这种元素一个一个的进行01背包处理,很好的提高了效率。)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=1e5+10;
int weight[MAX+50];
int value[MAX+50];
int n[MAX+105];
int dp[MAX+50];
int v;
void ZeroOnePack(int we,int va)
{
    for(int i=v; i>=we; i--)
    	dp[i]=max(dp[i],dp[i-we]+va);
}
void CompletePack(int we,int va)
{
	for(int i=we; i<=v; i++)
    	dp[i]=max(dp[i],dp[i-we]+va);
}
void MultiPack(int we,int va,int num)
{
    int k;
    if(num*we>=v)
    	CompletePack(we,va);
    else
    {
        k=1;
        while(num>k)
	{ 
            ZeroOnePack(k*we,k*va);
            num-=k;
            k*=2;
        }
	ZeroOnePack(num*we,num*va);
    }
}
int main()
{
    int c,m,i;
    scanf("%d",&c);
    while( c--)
    {
        scanf("%d%d",&v,&m);
        memset(dp,0,sizeof(dp));
        for( i=1; i<=m; i++)
	    scanf("%d%d%d",&weight[i],&value[i],&n[i]);
        for( i=1; i<=m; i++)
            MultiPack(weight[i],value[i],n[i]);
        printf("%d\n",dp[v]);
    }
}

猜你喜欢

转载自blog.csdn.net/shezjoe/article/details/81116363