背包问题(1) 0/1背包、完全背包

0/1背包问题

假设有n件物品,他们的体积分别为v[i],价值分别为w[i],有一个容量为m的背包,如何选择物品装入背包能够的得到最大的价值。(物品种类不超过N个)

  • 条件:每件物品至多只能选择1次
  • 状态定义:f [ i ],表示背包体积为 i 时的最大价值
  • 转移方程:f [ i ] = max( f [i] , f [ i - v [ i ] ] + w [ i ] )
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
	//N的值根据题意设定
	const int N = 1000;
	int f[N], v[N], w[N], n ,m;
	cin >> n >> m;
	//循环输入物品的体积和价值
	for(int i=0; i<=n; i ++)	
		cin >> v[i] >> w[i] ;
	//对于每件物品
	for(int i=1; i<=n; i++)
		//因为要使用上一次计算的某个体积时的最大价值,所以从大到小遍历,对于任何可能存在的体积情况,最大价值可能为
		//1.上一次计算该体积时的最大价值
		//2.上一次计算该体积 - v[i](刚好可以容纳当前物品体积)时的最大价值加上当前物品的价值
		for(int j=m; j>=v[i]; j--)
			f[j] = max( f[j] , f[j - v[i]] + w[i] );
	//不用循环遍历最后一步得到的f数组
	//1.因为第二层寻循环每次都从f[m]开始,所以f[m]必存在
	//2.如果物品体积全部大于m,则f[m]=0
	//3.每次循环对于f[m]来说,都会找到可以加入物品i的合适体积,也就是说这个体积首先可以装入物品i,其次还有
	//最大的剩余体积,这些最大的剩余体积的最大价值计算在循环的其他部分完成,并根据计算结果更新最大价值
	cout << f[m];
	return 0;
}	

完全背包问题

假设有n件物品,他们的体积分别为v[i],价值分别为w[i],有一个容量为m的背包,如何选择物品装入背包能够的得到最大的价值。(物品种类不超过N个)

  • 条件:每件物品至多能选择无数次
  • 状态定义:f [ i ],表示背包体积为 i 时的最大价值
  • 转移方程:f [ i ] = max( f [i] , f [ i - v [ i ] ] + w [ i ] )
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
	//N的值根据题意设定
	const int N = 1000;
	int f[N], v[N], w[N], n ,m;
	cin >> n >> m;
	for(int i=0; i<=n; i ++)	
		cin >> v[i] >> w[i] ;
	for(int i=1; i<=n; i++)
		//一个物品可以使用无数次,所以可以使用本次循环计算得到的小体积时的最大价值,从小到大遍历,对于任何可能存在的体积情况,最大价值可能为
		//1.上一次计算该体积时的最大价值
		//2.上一次计算该体积 - v[i](刚好可以容纳当前物品体积)时的最大价值加上当前物品的价值
		for(int j=v[i]; j<=m; j++)
			f[j] = max( f[j] , f[j - v[i]] + w[i] );
	cout << f[m];
	return 0;
}	
发布了16 篇原创文章 · 获赞 10 · 访问量 4917

猜你喜欢

转载自blog.csdn.net/weixin_44826484/article/details/105223780