不了解动态规划和选择dp的同学
先看一下这两篇文章
然后我们来做题
普通题+进阶题,图文详解,化零为整的解决多重背包puls问题!!!
多重背包
输入格式
输出格式
输出一个整数,表示最大价值。
数据范围
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
这题实际上是完全背包问题和01背包问题的结合
N的范围是<=100
O(N^3)的时间复杂度就可以通过
我们改编一下完全背包问题的闫氏DP分析法,即可
这是原来的
改编
在状态计算最后一行不同
代码实现
#include<iostream>
#include<cmath>
using namespace std;
int u[110],w[110],s[110];
int f[110][110];
int main(){
int N,V;
cin>>N>>V;
for(int i=1;i<=N;i++)
cin>>u[i]>>w[i]>>s[i];
for(int i=1;i<=N;i++){
for(int j=1;j<=V;j++){
//枚举每次选对于第i个数选几个是最优解
//k<=s[i]&&k*u[i]<=j保证不越界
for(int k=0;k<=s[i]&&k*u[i]<=j;k++){
f[i][j]=max(f[i][j],f[i-1][j-k*u[i]]+k*w[i]);
}
}
}
cout<<f[N][V];
return 0;
}
多重背包问题puls
多重背包问题puls,在多重背包的基础上,在题目上没有任何改变
但是增加了多重背包问题的数据范围
题目来自acwing
我们仔细想一下上面的做法
实际上上面是暴力的把数量为s的物品i
转成了同价值的,同容量的s个物品
例如,我们看一下样例和样例展开图
原来输入的是这样的
我们在处理时,实际上是这样的
这样在s[i]太大时,我们处理数据量就太大了
这种算法太过暴力
为了优化这种算法
我们引入一种新的算法概念
二进制优化
我们每次都暴力枚举一个数,我们在思考,有没有办法,可以减少枚举的次数
我们来看一个图
此图已被我修改更好理解
原图的来源:哔哩哔哩一只小傲风
我们仔细观察二进制数
会得出一个惊人但是本该如此的理论
这个十个编号,对应的二进制数
能组成任意一个十位二进制数
能组成任意一个十位二进制数等价于能组成任意一个小于1024的数字
在题目数据范围中,s[i]小于2000
随便举一个例子,例如1888
那我们可以把1888这个数的前1023,都分成如上分
然后最后一份为1888-1023=865
如果我们要组成1866
那我们可以使用1+8+32+64+128+256+512+865=1866
也就是我们可以拿11个编号的数,组成2000以内任意数
在暴力算法下,本来要枚举两千次的计算量
直接优化为了11次
本来我们的暴力算法,是等价于,把s[i]个数量的物品拆分成s[i]个
现在我们拆分s[i]个物品,至多拆分为11个!!!
所以夸张的说,时间复杂度最高可降低一千倍
在读入数据的时候,把s[i]件物品i分割成至多11件物品组
可降低时间复杂度,从而通过代码
代码实现
#include<iostream>
using namespace std;
const int N = 12010, M = 2010;
int n, m;
int v[N], w[N]; //逐一枚举最大是N*logS
int f[M]; // 体积<M
int main()
{
cin >> n >> m;
int cnt = 0; //分组的组别
for(int i = 1;i <= n;i ++)
{
int a,b,s;
cin >> a >> b >> s;
int k = 1; // 组别里面的个数
while(k<=s)
{
cnt ++ ; //组别先增加
v[cnt] = a * k ; //整体体积
w[cnt] = b * k; // 整体价值
s -= k; // s要减小,代表其他元素已经建组
k *= 2; // 组别里的个数增加,换二进制表示
}
//检测是否剩余,新建一组
if(s>0)
{
cnt ++ ;
v[cnt] = a*s;
w[cnt] = b*s;
}
}
n = cnt ; //枚举次数由个数变成组别
//直接当01背包模板题写
for(int i = 1;i <= n ;i ++)
for(int j = m ;j >= v[i];j --)
f[j] = max(f[j],f[j-v[i]] + w[i]);
cout << f[m] << endl;
return 0;
}
问题:为什么不会影响最后结果
因为11个组别可以组成2000以内任意数,也就是枚举这11个组
和枚举2000个数,能得到的全部结果是一样的
所以能得到的最优解,价值最大的方案也是一样的
标签:11,多重,背包,int,算法,枚举,puls From: https://blog.csdn.net/XYY369/article/details/137122380