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]);
}
}