01背包问题
有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
未优化版本:
for (int i=1;i<=n;++i) { for (int j=v;j>=0;--j) {
if(c[i]<=j)//如果当前物品可以放入当前空间的背包
f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);
else f[i][j]=f[i-1][j];//如果当前物品放不进去,那么继承前i个物品在当前空间大小时的价值
}
}
优化版本:
/*
01背包
适用于输入格式如下的问题,出现问题请自行调整:
第一行两个整数M, N分别表示背包空间与物品总数;
第2到N+1行每行两个整数,分别表示这类物品每个的价值和所需空间。
*/
#include<cstdio>
const int MAXM=10001,MAXN=51;
int m,n;
int w[MAXN],c[MAXN];
int f[MAXM];
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
scanf("%d%d",&m,&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=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+c[i]);
printf("%d\n",f[m]);
return 0;
}
01背包问题(完全背包)
未优化版本:
for(int i = 0 ; i < n ; i ++)
{
for(int j = 1 ; j <= v ; j++)
{
if(c[i]<=j)
f[i][j] = max(f[i-1][j],f[i][j-c[i]]+w[i]);
else
f[i][j]=f[i-1][j];
}
}
优化版本:
/*
完全背包,输入规则:
第一行两个整数M, N分别表示背包空间与物品总数;
第2到N+1行每行两个整数,分别表示这类物品每个的价值和所需空间。
*/
#include<cstdio>
const int MAXM=10001,MAXN=51;
int m,n;
int w[MAXN],c[MAXN];
int f[MAXM];
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
scanf("%d%d",&m,&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<=m;j++)
f[j]=max(f[j],f[j-w[i]]+c[i]);
printf("%d\n",f[m]);
return 0;
}
01背包问题(多重背包)
未优化版本:
#include<bits/stdc++.h>
using namespace std;
int dp[1005];
int weight[1005],value[1005],num[1005];
int main()
{
int n,m;
cin>>n>>m;
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++)
cin>>weight[i]>>value[i]>>num[i];
for(int i=1; i<=n; i++)//每种物品
for(int k=0; k<num[i]; k++)//其实就是把这类物品展开,调用num[i]次01背包代码
for(int j=m; j>=weight[i]; j--)//正常的01背包代码
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
cout<<dp[m]<<endl;
return 0;
}
优化版本说明:
把原始的数量的物品拆分可以组合的多个商品,
比如Ci = 14,我们可以把它化成如下4个物品:
重量是Wi,体积是Vi
重量是2 * Wi , 体积是2 * Vi
重量是4 * Wi , 体积是4 * Vi
重量是7 * Wi , 体积是7 * Vi
优化版本:
/*
多重背包,输入格式:
第一行,一个整数n,物品数量;
第二行,n个整数,第i个整数表示第i个物品的价格bi;
第三行,n个整数,第i个整数表示第i个物品的数量ci;
第四行,一个整数m,背包空间。
*/
#include<cstdio>
const int MAXM=10001,MAXN=6001;
int v[MAXM],w[MAXM];
int f[MAXN];
int n,m,p;
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x,y,s,t=1;
scanf("%d%d%d",&x,&y,&s);
for(;s>=t;t<<=1)
{
v[++p]=x*t;
w[p]=y*t;
s-=t;
}
v[++p]=x*s;
w[p]=y*s;
}
for(int i=1;i<=p;i++)
for(int j=m;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);
printf("%d\n",f[m]);
return 0;
}
参考文章:
https://www.cnblogs.com/Kalix/p/7622102.html