背包问题
1.01背包:
for(int i=1;i<=m;i++)
for(int j=t;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+c[i]);
例题:采药(模板) OnlineJudge 衡中OI
#include<bits/stdc++.h>
using namespace std;
int c[101],w[101],f[101]; //w:重量,c:单个价值
int main()
{
int t,m;
cin>>t>>m;
for(int i=1;i<=m;i++) cin>>w[i]>>c[i];
for(int i=1;i<=m;i++)
for(int j=t;j>=w[i];j--)
if(f[j]<f[j-w[i]]+c[i])
f[j]=f[j-w[i]]+c[i];
cout<<f[t];
return 0;
}
2.完全背包:
for(int i=1;i<=n;i++)
for(int j=w[i];j<=m;j++) //只有这里和01背包不同,遍历的顺序正好与01背包相反
f[j]=min(f[j],f[j-w[i]]+c[i]);
例题:完全背包问题 OnlineJudge 衡中OI
#include<bits/stdc++.h>
using namespace std;
int w[201],c[201],f[201];
int main()
{
int m,n;
cin>>m>>n;
for(int i=1;i<=n;i++) cin>>w[i]>>c[i];
for(int i=1;i<=n;i++)
for(int j=w[i];j<=m;j++) //遍历顺序从i物品的重量数开始,因为j-w[i]不能等于0
if(f[j]<f[j-w[i]]+c[i]) f[j]=f[j-w[i]]+c[i];
cout<<"max="<<f[m];
return 0;
}
3.多重背包
/*
以下是多重背包转01背包的模板
*/
int t=1;
while(s>=t)
{ //二进制是个好东西,把整个数分成1,2,4,8,16,...等等,
c[++num]=x*t; //可以遍历到所有情况,就不再需要1.2.3.4.5...这么遍历耗时了。
w[num]=y*t;
s-=t;
t*=2;
}
c[++num]=x*s; //将多重背包转化为01背包,可以更加方便
w[num]=y*s;
例题:庆功会 OnlineJudge 衡中OI
#include<bits/stdc++.h>
using namespace std;
int n,m,w[10001],c[10001],num,f[10001];
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1,x,y,s;i<=n;i++)
{
int t=1;
cin>>x>>y>>s;
while(s>=t)
{
c[++num]=x*t;
w[num]=y*t;
s-=t;
t*=2;
}
c[++num]=x*s;
w[num]=y*s;
}
for(int i=1;i<=num;i++)
for(int j=m;j>=c[i];j--) //下面还是和01背包的遍历方式一样
f[j]=max(f[j],f[j-c[i]]+w[i]);
cout<<f[m];
return 0;
}
--END--
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/15819352.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!