动态规划之多重背包【暴力->优化】(实例讲解优化过程&原理)

给出多重背包的一个例题:
在这里插入图片描述

这里数据量很小,可以直接暴力去做。可以发现,和01背包例题的主要区别就是每种物品不是固定的一件,而是最多不超过s[i]件,就是所说的 “多重背包是01背包的一个扩展”(在下方的优化方法中会有相应的解释/证明),所以体积在枚举时要从大到小枚举 。

下面讲一下比较重要的三处:

f[i]:总体积是 i 的情况下,最大价值是多少

原始 &未经处理的核心步骤: for(int i=0; i<n; i++)
{
for(int j=m; j>=v[i]; j- -)
f[j] = max(f[j], f[j - v[i]] + w[i], f[j - 2* v[i]] + 2* w[i]…);
}

初始化时有两种操作:

  1. 如果把所有状态都初始化为 0了,那么f[m]就是答案
  2. 若只令f[0]=0,其他的都是负无穷,则从f[0~m]中选一个最大值 即:
    1.1. f[i]=0。答案:f[m]
    2.2. f[0]=0, f[i]=-inf & i!=0。答案:max{f[0… m]}
// AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 110;

int n,m,f[N];

int main()
{
    
    
	cin >> n >> m;
	for(int i=0; i<n; i++)
	{
    
    
	    int v,w,s;
	    cin >> v >> w >> s;
	    for(int j=m; j>=0; j--)
	        for(int k=1; k<=s && k*v<=j; k++)
	            f[j] = max(f[j], f[j-k*v]+k*w); 
	} 
	cout << f[m] << endl;
	return 0;
}

当数据量变大时,再去暴力的话,10^9会超时。 需要用到多重背包的二进制优化方法

在这里插入图片描述
为了帮助理解二进制的优化方法,我们先来看一下 “怎么把多重背包问题转化为01背包问题”

假设第 i 个物品的体积是 v,价值是 w,件数是 s。实际上可以把这个物品拆开,直接拆成s份,每份的体积是 v’,价值是 w’,放到物品堆中去,每份只能用一次,这就变成了一个01背包问题 。

但是这种拆法的复杂度是十分高的,也会达到1e9。那么我们可以考虑如何使得划分的份数减少的同时,还能保证…

我们可以把第 i 种物品分成 logS(以2位底上取整)份 【时间复杂度:1000 x logS x 2000 = 2 x 1e7 】。下面用一个例子来解释:给定任意一个数s,问最少可以把s分成多少个数,使得这些数能组成1~n 的所有数。分成的这些数有2种选法,选和不选,而且它们要能够组成 1~s 的所有数(并且不能凑到>s,即这些数的和不能>s)。

特例:
s=7,log7上取整为3。2^0=1 , 2^1=2 , 2^2=4, 1 2 4可以组成1~7所有的数
s=10, log10上取整为4…1 2 4 8。但这4个数的和>10,放不下这么多。
这个时候就在 s 够用的情况下,不断减去前面的数,即得到1 2 4 3 这四个数,经过验证,符合要求。

// AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;

int n,m,f[N];

struct Good {
    
    
    int v,w;
};

int main()
{
    
    
	vector<Good> goods;
	cin >> n >> m;
	for(int i=0; i<n; i++)
	{
    
    
		int v, w, s;
		cin >> v >> w >> s;
		for(int k=1; k<=s; k*=2)
		{
    
    
			s -= k;
			goods.push_back({
    
    v*s,w*s});
		}
		if(s>0)  goods.push_back({
    
    v*s,w*s});
	}
	
	for(auto good:goods)
	    for(int j=m; j>=good.v; j--)
	        f[j] = max(f[j], f[j-good.v]+good.w);
	
	cout<<f[m]<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Luoxiaobaia/article/details/108956943