目录
当前动态规划中的背包问题主要分为三类:01背包、完全背包以及多重背包。其中,多重背包即01背包和完全背包的变种。
(一)01背包C++模板代码
#include <stdio.h>
#include <string.h>
int f[1010],w[1010],v[1010];//f记录不同承重量背包的总价值,w记录不同物品的重量,v记录不同物品的价值
int main(){
int t,m,i,j;
memset(f,0,sizeof(f)); //总价值初始化为0
scanf("%d %d",&t,&m); //输入背包承重量t、物品的数目m
for(i=1;i<=m;i++)
scanf("%d %d",&w[i],&v[i]); //输入m组物品的重量w[i]和价值v[i]
for(i=1;i<=m;i++){ //尝试放置每一个物品
for(j=t;j>=w[i];j--){//倒叙是为了保证每个物品都使用一次
f[j]=max(f[j-w[i]]+v[i],f[j]);
//在放入第i个物品前后,检验不同j承重量背包的总价值,如果放入第i个物品后比放入前的价值提高了,则修改j承重量背包的价值,否则不变
}
}
printf("%d\n",f[t]); //输出承重量为t的背包的总价值
return 0;
}
(二)完全背包C++模板代码
#include<cstdio>
#include<algorithm>
using namespace std;
int w[300],c[300],f[300010];
int V,n;
int main()
{
scanf("%d%d",&V,&n);
for(int i=1; i<=n; i++)
{
scanf("%d%d",&w[i],&c[i]);
}
for(int i=1; i<=n; i++)
for(int j=w[i]; j<=V; j++)//注意此处,与0-1背包不同,这里为顺序,0-1背包为逆序
f[j]=max(f[j],f[j-w[i]]+c[i]);
printf("max=%d\n",f[V]);
return 0;
}
(三)多重背包C++模板代码
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[100007],n,m,a[105],c[105],count;
void zeropack(int cost,int value)
{
for(int i=m;i>=cost;i--)
dp[i]=max(dp[i],dp[i-cost]+value);
// cout<<"01"<<endl;
}
void completepack(int cost,int value)
{
for(int i=cost;i<=m;i++)
dp[i]=max(dp[i],dp[i-cost]+value);
//cout<<"complete"<<endl;
}
void multipack(int cost,int value,int num)
{
if(num*cost>=m)
{
completepack(cost,value);
return;
}
int k=1;
while(k<num)
{
zeropack(k*cost,k*value);
num-=k;
k*=2;
}
zeropack(num*cost,num*value);
}
int main()
{
// freopen("cin.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
memset(dp,0,sizeof(dp));
count=0;
for(int i=1;i<=n;i++)
{
multipack(a[i],a[i],c[i]);
}
for(int i=1;i<=m;i++)
{
if(dp[i]==i) count++;
//printf("dp[]=%d\n",dp[i]);
}
printf("%d\n",count);
}
return 0;
}