首页 > 编程语言 >动态规划 选择dp:多重背包+多重背包puls----中专生刷算法

动态规划 选择dp:多重背包+多重背包puls----中专生刷算法

时间:2024-03-29 13:03:35浏览次数:30  
标签:11 多重 背包 int 算法 枚举 puls

不了解动态规划和选择dp的同学

先看一下这两篇文章

动态规划:选择dp及优化01背包问题-CSDN博客

动态规划:完全背包问题----中专生刷算法-CSDN博客

然后我们来做题

普通题+进阶题,图文详解,化零为整的解决多重背包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

相关文章

  • T555Pulse 555做为多谐振荡器的计算器A calculator for multi harmonic oscillators
    本软件很便宜,就是2包烟的钱。可以用来计算555的普通多谐震荡器电路的电阻、电容、周期、频率、高电平时间,低电平时间、占空比这类的东西的相互换算。Thissoftwareisverycheap,itcostsonly2packsofcigarettes.Itcanbeusedtocalculatethemutualconversionofr......
  • 2024-03-27:用go语言,多维费用背包。 给你一个二进制字符串数组 strs 和两个整数 m 和 n
    2024-03-27:用go语言,多维费用背包。给你一个二进制字符串数组strs和两个整数m和n,请你找出并返回strs的最大子集的长度,该子集中最多有m个0和n个1。如果x的所有元素也是y的元素,集合x是集合y的子集。输入:strs=["10","0001","111001","1","0"],m=......
  • 图解二维完全背包问题——降维打击
    例题例题:518.零钱兑换II概述:给你一个整数数组coins表示不同面额的硬币,另给一个整数amount表示总金额。请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回0。假设每一种面额的硬币有无限个。题目数据保证结果符合32位带符号整数。......
  • 【DP】01背包问题与完全背包问题
    一、01背包问题有 N件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。输入格式第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包......
  • 01背包
    0/1背包二维形式二维数组f[][]被用作动态规划的辅助数组,它的作用是存储在不同的背包容量和不同的物品选取情况下所能达到的最大总价值。具体来说,f[i][j]表示在前i个物品中选取,并且背包容量限制为j时所能达到的最大总价值。在动态规划的过程中,f[i][j]的计算依赖于前一行......
  • 【动态规划】【同余前缀和】【多重背包】[推荐]2902. 和带限制的子多重集合的数目
    本文涉及知识点动态规划汇总C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例包括课程视频C++算法:滑动窗口总结多重背包LeetCode2902.和带限制的子多重集合的数目给你一个下标从0开始的非负整数数组nums和两个整数l和r。请你返回nums中子多重集......
  • 算法Day2—动态规划(剑指offer63+01背包问题(1))
    剑指offer63:股票的最大利润题目:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?转移方程:dp[i]=max(dp[i−1],第i日卖出的最大利润中的最大值)classSolution{publicintmaxProfit(int[]prices){intcost=......
  • 一文彻底搞懂背包问题
    文章目录1.01背包问题2.完全背包问题3.多重背包问题01背包、完全背包和多重背包问题都属于经典的背包问题,这些问题都可以通过动态规划来解决,它们在动态规划中有着不同的特点和解法,其中状态转移方程是解决这些问题的核心。通过填表的方式,逐步求解最优解,最终得到问题......
  • 多维背包问题动态规划算法
    #include <iostream>  #include <vector>  using namespace std;//定义物品结构体 struct Item {    int id;    int weight;    int volume;    int value;};//初始化背包的容量限制 const int MAX_WEIGHT=50;const ......
  • (41/60)0-1背包(二维数组、一维数组)、分割等和子集
    有点抽象0-1背包卡码网:携带研究材料(第六期模拟笔试)动态规划思路二维:意义:0~i物品内,放进容量为j的背包,最大价值为dp[i][j]递推:dp[i][j]=max(dp[i-1][j-weight[i],dp[i-1][j])初始化:第一列为0,第一行j>=weight[0]时赋值为value[0]遍历:先背包再物品/先物品再背包均可(......