目录

蓝桥杯备考背包初次了解以及01背包

目录

蓝桥杯备考:背包初次了解以及01背包

背包就是说给一个有容量的背包,比如说给一个总体积V,给一堆物品 每个物品都有对应的体积

每个物品都有对应的闪光值,我们要让这个闪光值最大,但是不能超过总体积,

背包问题有多种变体

01背包表示每个物品要么被选要么不被选

完全背包表示每个物品可以被选多次

分组背包表示把物品分组,每个组只能选一个

多重背包表示每个物品都是有数量的

问法除了有求最大的闪光度,也可以是求方案总数,也可以是求方案可行性或者输出具体的方案

https://i-blog.csdnimg.cn/direct/b432aa2ff6304d89a328776c151a57ab.png

https://i-blog.csdnimg.cn/direct/af601fcd77c04a7ca33d12cd32c15690.png

这是一道很经典的01背包模板题,我们先做一下第一小问

我们还是老样子,按顺序来分析

step1:确定状态表示 我们用一维的化就是表示f[i]是从1到i个物品里选出最大价值,但是我们的限制条件是有两个的呀?我们不能就这么用一个一维的dp数组解决它,我们应该开个二维的

f[i][j]表示的是 从1到i个物品里选出体积不超过j的最大价值

step2:确认状态转移方程

​​​​ https://i-blog.csdnimg.cn/direct/06d676eaa72f4c67bd5179e9a6a0ac2e.png

当然,这里我们一定要注意的是,如果要选a[i]这个物品的话呢,前提是j必须大于等于a[i]

step3: 初始化

https://i-blog.csdnimg.cn/direct/c3f22cc6455d4dbeb009ad274313a276.png

step4:确定填表顺序,应该是从上到下的

好的,话不多说,我们来实现一下我们的代码

#include <iostream>
using namespace std;
const int N = 1e4+10;
int v[N],w[N];
int n,m;
int f[N][N];
int main()
{
	cin >> n >> m;
	for(int i = 1;i<=n;i++)
	{
		cin >> v[i] >> w[i];
	}
	for(int i =1;i<=n;i++)
	{
		for(int j = 1;j<=m;j++)
		{
			f[i][j] = f[i-1][j];
			if(j>=v[i])
			{
				f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]); 
			}
		}
	}
	cout << f[n][m] << endl;
	
	
	
	
	
	
	return 0;
}

除此之外,我们还需要再分析一下第二问

step1:f[i][j]表示从1到i个物品里选出体积刚好为j的价值最大的物品

step2:确定状态转移方程,实际上和第一问是一样的 https://i-blog.csdnimg.cn/direct/44ac156842bb48b1a42315d952c0ed42.png

step3:初始化:这里就开始出现差别了,我们恰好的话呢

https://i-blog.csdnimg.cn/direct/be53fa57aeb34082bb28979c7e3c6d0f.png

肯定是有些格子不能存值的,因为体积加起来不可能刚好满足所有下标,最显而易见的就是图上第一行f[0][1~4]选0个物品恰好体积是1到4,这个是一定不可能的,我们可以把它设置为负无穷,然后取max的时候是不影响的,特殊的f[0][0]是可以填0的,因为选0个物品总价值刚好为0是可以的

step4 从上到下填表

实现代码

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e3+10;
int v[N],w[N];
int n,m;
int f[N][N];
int main()
{
	memset(f,-0x3f,sizeof f);
	f[0][0] = 0; 
	cin >> n >> m;
	for(int i = 1;i<=n;i++)
	{
		cin >> v[i] >> w[i];
	}
	for(int j = 0;j<=n;j++)
	{
		f[j][0] = 0;
	 } 
	for(int i =1;i<=n;i++)
	{
		for(int j = 1;j<=m;j++)
		{
			f[i][j] = f[i-1][j];
			if(j>=v[i])
			{
				f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]); 
			}
		}
	}
if(f[n][m] < 0) cout << 0 << endl;
else cout << f[n][m] << endl;
	
	
	
	
	
	
	return 0;
}

https://i-blog.csdnimg.cn/direct/53f97aab718e4c0199049c0ca0e5cd55.png