加载中…

返回上一页

背包问题

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;
}
posted @ 2022-01-18 19:10  1Liu  阅读(75)  评论(0编辑  收藏  举报