【完全背包】详细解答+详细代码+一维数组解决+二维数组解决

【完全背包】有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

1.【题目描述】

有n种物品和一个容量为v的背包,每一种背包无限使用,在不超过背包容量的前提下,求最大价值。
物品3 背包容量6

物品编号123
重量243
价值376

2.【递推思路】

1.【基本思路】

1.确定状态变量(函数)
2.确定状态转移方程(递推关系)
3.确定边界

2.【本题思路】

首先完全背包问题和0-1背包有什么不同的地方呢,0-1背包每一件物品只能被装一次,完全背包就是可以无限制的装,物品数量没有限制。
这个问题类似于01背包问题,所不同的就是每种物品无限制使用。

for(int i=1;i<=n;i++) //物品 
{
	for(int j=1;j<=m;j++) //容量 
	{
		if(j<w[i]) //装不下 
			f[i][j]=f[i-1][j]; //就等于i-1件物品容量等于j时候的价值 
		else
			f[i][j]=max(f[i-1][j],f[i][j-w[i]]+v[i]);//装得下分为两种情况1.装 2.不装 
	}
}

在这段代码可以看出,与0-1背包不同的地方是状态转移方程有所区别。
0-1背包状态转移方程:
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]
完全背包状态转移方程:
f[i][j]=max(f[i-1][j],f[i][j-w[i]]+v[i])
当不取的时候都是一样的最大价值等于f[i-1][j],等于i-1件物品在容量等于j的时候的最大值
当要取的时候这里有不同的地方
0-1背包是每一件物品只能选取一次 ,在解决0-1背包问题的时候我们需要找到f[i-1][j-w[i]最大价值。因为我们当前物品重量等于w[i],背包总容量等于j,我们就需要找到j-w[i]容量时第i-1件物品的时候最大价值然后加上我们这件物品的价值。
完全背包并不是找到上一件物品背包容量等于j-w[i]的时候,而是找到当前物品情况下j-w[i]的最大值,因为我们的物品可以无限制的使用,f[i][j-w[i]]+v[i]就是在求最大价值,是在放当前物品的时候容量等于j-w[i]的时候最大价值加上现在物品的价值,0-1背包是找到上一件物品背包容量等于j-w[i]的时候最大价值加上现在物品的价值,这就是0-1背包和完全背包不同的地方。

3.【二维数组解决完全背包问题】

#include <bits/stdc++.h>
using namespace std;
int f[100][100];//状态函数f[i][j]表示第i件物品容量为j最大价值
int v[100]; 
int w[100];
/*
函数功能:求完全背包 
函数形参:物品数量和背包容量
函数返回值:返回最大值 
*/  
int fun(int n,int m)
{
	for(int i=1;i<=n;i++) //物品 
	{
		for(int j=1;j<=m;j++) //容量 
		{
			if(j<w[i]) //装不下 
				f[i][j]=f[i-1][j]; //就等于i-1件物品容量等于j时候的价值 
			else
				f[i][j]=max(f[i-1][j],f[i][j-w[i]]+v[i]);//装得下分为两种情况1.装 2.不装 
		}
	}
		return f[n][m];
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>w[i]>>v[i];
	cout<<fun(n,m);
	return 0;
}

4.【一维数组解决完全背包问题】

#include <bits/stdc++.h>
using namespace std;
int f[100];//状态函数f[j]表示第i件物品容量为j最大价值
int v[100]; 
int w[100];
/*
函数功能:求完全背包 
函数形参:物品数量和背包容量
函数返回值:返回最大值 
*/   
int fun(int n,int m)
{
	for(int i=1;i<=n;i++) //物品 
	{
		for(int j=w[i];j<=m;j++) //容量 
		{
			f[j]=max(f[j],f[j-w[i]]+v[i]);//装得下分为两种情况1.装 2.不装 
		}
	}
		return f[m];
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>w[i]>>v[i];
	cout<<fun(n,m);
	return 0;
}

仅供参考!

  • 31
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值