算法:多重背包问题dp

文章目录

    • 一、多重背包问题特点
      • 1.1、多重背包问题的特征
      • 1.2、解决多重背包问题的基本方法
        • 典型例题:AcWing——多重背包问题I
      • 1.3、二进制优化
        • 1.3.1、二进制优化的思想
        • 1.3.2、多重背包问题的二进制优化

在这里插入图片描述

一、多重背包问题特点

多重背包问题是背包问题的又一变种,它在0-1背包和完全背包问题的基础上增加了一个限制:每种物品i除了有一个重量w[i]和价值v[i]外,还有一个最大可用数量n[i]。这意味着每种物品i可以被选取的次数最多是n[i]次,而不是只有一次(0-1背包问题)或无限次(完全背包问题)。

1.1、多重背包问题的特征

  1. 有限的物品数量:每种物品有一个最大数量限制,不能无限制地选择。
  2. 背包容量限制:存在一个容量限制,所有选取的物品的总重量不能超过这个限制。
  3. 优化目标:目标是在不超过背包容量的前提下,最大化背包内物品的总价值。
  4. 复杂度:时间和空间复杂度取决于具体的实现方法,一般时间复杂度为O(V*sum(n[i]))

1.2、解决多重背包问题的基本方法

解决多重背包问题的基本思路是利用动态规划,其中最直观的方法是使用二维DP数组dp[i][j],表示考虑前i种物品,在不超过重量j的情况下的最大价值。和0-1背包问题的区别在于物品i能取n[i]次,因此状态转移方程可以写为:

for(int k=0;k<=n[i];++k)
	if(j-k*weight[i]>=0)
		dp[i][j]=max(dp[i][j],dp[i-1][j-k*weight[i]]+k*value[i]);

这里,k是从0n[i]的整数,表示选择第i种物品k次的可能性。

由于这种方法会导致较高的时间复杂度,时间复杂度为O(V*sum(n[i])),特别是当n[i]的值很大时,常常需要使用其他技巧。

典型例题:AcWing——多重背包问题I

AcWing:多重背包问题I
按照以上思路,并且按照0-1背包一样的思路,进行降维优化。

    for(int i=0;i<N;++i)
        for(int j=V;j>=volume[i];--j)
            for(int k=0;k<=n[i];++k)
                if(j-k*volume[i]>=0)
                    dp[j]=max(dp[j],dp[j-k*volume[i]]+k*value[i]);

本题可以书写代码为:

#include<bits/stdc++.h>
using namespace  std;
int dp[101];
int main(void){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int N,V;
    cin>>N>>V;

    vector<int> volume(N);
    vector<int> value(N);
    vector<int> n(N);

    for(int i=0;i<N;++i){
        cin>>volume[i]>>value[i]>>n[i];
    }
    for(int i=0;i<N;++i)
        for(int j=V;j>=volume[i];--j)
            for(int k=0;k<=n[i];++k)
                if(j-k*volume[i]>=0)
                    dp[j]=max(dp[j],dp[j-k*volume[i]]+k*value[i]);
    cout<<dp[V];
    return 0;
}

1.3、二进制优化

1.3.1、二进制优化的思想

对于任何一个数,我们可以将其进行二进制拆分。即任何一个10进制数都能写成二进制数的形式。
比如:3=1+2=11B、10=2+8=1010B。

如果我们对于一个数,例如10,取出小于其的所有二进制位,即1B,10B,100B,1000B,那么我们必然能够选出其中的某些位来凑成10,并且对于小于10的任何一个正整数也可以被凑成,即选取其中若干位有:1B、10B、11B、100B、101B、110B、111B、1000B、1001B···。即,如果我们有一个物品,它能够被选择小于等于n次,我们可以通过选择其中的某些位来实现选择的所有情况。

那么我们把一个物品可以最多选择n次的问题,按照未优化的多重背包问题需要进行O(V*sum(n[i]))次计算取最大值 变成了
考虑在logn个物品中选择其中的某些物品,取最大值 的问题了。按到理来说,logn个物品要么被选要么不被选,一共是2的logn次方种情况,也就是n种情况;但是如果我们把这个问题转化成0-1背包问题,即利用动态规划来考虑,就变成了O(V*sum(logn[i]))次了。当n[i]<=2000时,logn[i]<=3.301,减少了一千倍计算量。

因此,我们对于n[i],可以进行二进制拆分,将n[i]个物品按照二进制拆分,变成若干堆,每次选择只能一次全选,这样使得我们需要考虑的物品变成logn[i]个,多重背包问题变成了一个0-1背包问题,即这logn[i]个物品,要么被选,要么不被选,能够取得的最大值。我们通过上述叙述可以知道logn[i]个物品的所有被选择的情况,刚好构成了0~n[i]中的所有数字。

由于一个物品的数量n不一定是2的整数倍,因此我们在考虑二进制的时候,因为我们的目的是凑成0~ n,因此我们在考虑二进制的时候,我们考虑到小于等于n/2位即可,它们能满足0~ k种情况(k<=n/2),然后剩余的n-k部分直接单独成一块就行,这样,能满足n-k~ k+n-k种情况,合并起来就是0~n中情况。合并时也许会有相同的情况,但是这并不影响,相当于不同方式的物品的选取能达到同样的最大值,我们只需要能让物品数量区间等于0 ~ n即可。

1.3.2、多重背包问题的二进制优化

通过二进制拆分,我们将m个物品每个最多选n[i]次的多重背包问题,转换成了 sum(logn[i])个物品的0-1背包问题。相当于进行了问题转换。

代码:

#include<bits/stdc++.h>
using namespace  std;
int dp[2002];
int main(void){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int N,V;
    cin>>N>>V;

    vector<int> value;
    vector<int> volume;
    for(int i=0;i<N;++i){//构建二进制拆分物品
        int w,v,num;
        cin>>w>>v>>num;//w单物品体积,v单物品价值,num可选数量
        int s=num;
        int b=1;
        while(b<=s){//注意b必须是小于num,且不能是最高位 如1010B,b不能是1000B
            value.push_back(b*v);
            volume.push_back(b*w);
            s-=b;
            b*=2;
        }
        if(s>0){
            value.push_back(s*v);
            volume.push_back(s*w);
        }
    }
    
    N=value.size();//更新物品数量
    
    for(int i=0;i<N;++i)
        for(int j=V;j>=volume[i];--j)
            dp[j]=max(dp[j],dp[j-volume[i]]+value[i]);

    cout<<dp[V];
    return 0;
}

位数关系即:

        int s=num;
        int b=1;
        num=log2(num);
        num=pow(2,num-1);
        while(b<=num){
            value.push_back(b*v);
            volume.push_back(b*w);
            s-=b;
            b*=2;
        }
        if(s>0){
            value.push_back(s*v);
            volume.push_back(s*w);
        }
        int s=num;
        int b=1;
        num=num>>1;
        while(b<=num){
            value.push_back(b*v);
            volume.push_back(b*w);
            s-=b;
            b*=2;
        }
        if(s>0){
            value.push_back(s*v);
            volume.push_back(s*w);
        }

官方:

#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/533773.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

钢条切割问题:动态规划算法的典型应用

一、引言 在工业生产和物流管理中&#xff0c;钢条切割问题是一个常见的优化问题。企业在购买长钢条并将其切割为短钢条出售时&#xff0c;往往面临着如何切割以最大化利润的问题。这个问题不仅关系到企业的成本控制和利润最大化&#xff0c;也涉及到资源的有效利用和生产效率…

QA:缺少VC运行时库导致VisualBox和XShell运行出错

前言 启动软件时&#xff0c;特别是绿色版软件&#xff0c;有时会遇到“缺少xxx.dll文件”&#xff0c;导致软件启动失败。 注&#xff1a;xxx.dll是动态链接库&#xff08;DLL&#xff09;文件&#xff0c;包含了程序运行所需的函数和资源。 内容 象上面这种类型的错误&…

漫画|数据工程师面试常见问题之数据倾斜

话说&#xff0c;闹钟一响&#xff0c;现实照进梦想&#xff0c;又是李大虎面试找工作的一天。 李大虎心里一直有个想法&#xff0c;如果一天睡20个小时&#xff0c;然后这20个小时全做美梦&#xff0c;醒来的4个小时用来吃喝拉撒&#xff0c;这样岂不就和那些富二代一样了&am…

AI应用实战2:使用scikit-learn进行回归任务实战

代码仓库在gitlab&#xff0c;本博客对应于02文件夹。 1.问题分析 在此篇博客中我们来对回归任务进行实战演练&#xff0c;背景是直播带货平台的业绩预测。第一步&#xff0c;就是分析问题。 问题痛点&#xff1a; 在直播带货平台上&#xff0c;由于市场环境多变、用户行为复…

【网站项目】校园二手交易平台小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Python爬虫网络实践:去哪儿旅游数据爬取指南

Python爬虫网络实践&#xff1a;去哪儿旅游数据爬取指南 在这个博客中&#xff0c;我们将探索如何使用 Python 来进行网络数据抓取&#xff0c;并以抓取旅游数据为例进行演示。我们将通过一个简单的示例来说明如何利用 Python 中的常用库进行网页抓取&#xff0c;从而获取旅游…

ABAP 增强篇

文章目录 ABAP 增强篇第一代增强-基于源码增强用户出口子程序所能使用的数据变量VA01增强示例 第二代&#xff1a;基于函数出口增强&#xff08;FUNCTION&#xff09;SMOD与COMD查找出口函数出口对象激活&#xff08;SMOD&#xff09;增强详细说明文档示例&#xff1a;通过出口…

vulhub靶场shiro系列漏洞复现CVE-2010-3863、CVE-2016-4437(shiro550)、CVE-2020-1957、shiro721

目录 shiro简介 shiro漏洞成因 shiro550 shiro721 利用过程 CVE-2010-3863&#xff08;未授权访问&#xff09; 简介 CVE-2016-4437(shiro550) 简介 CVE-2020-1957&#xff08;未授权访问&#xff09; 漏洞影响 简介 url处理过程 shiro721 影响版本 简介 利用 …

2024全国现代流通经济创新大会暨城郊大仓基地高质量建设论坛日程发布

2024年4月19日 中国平谷 建设城郊大仓基地 创新现代流通经济 一、大会开幕式&主论坛 时间&#xff1a;9:00-12:00 地点&#xff1a;博物馆一楼 报告厅 主持人&#xff1a;中国商业联合会商贸物流与供应链分会会长干为 08:30-09:00 大会入场&宣传片视频 09:00-0…

iOS 启动速度优化

启动耗时&#xff1a;点击App后到首帧显示耗费的时间。 阶段分析&#xff1a;premain、postmain&#xff0c;也就是main函数执行前和main函数执行后。 耗时检测&#xff1a;Instrument->App Launch Premain 减少动态库数量&#xff1a;启动时程序会加载动态库&#xff0c;…

Acrobat Pro DC 2021---PDF编辑与管理,打造高效PDF工作流程 含Mac+win

Acrobat Pro DC 2021包括全面的PDF编辑、OCR识别、多种输出格式转换以及强大的文件安全性保护。用户可轻松编辑、合并、转换PDF文件&#xff0c;同时支持将扫描文档转换为可编辑的PDF。可将PDF转换为Word、Excel、PowerPoint等格式&#xff0c;提高工作效率。 Mac电脑&#xf…

vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户

1.后端返回的json数据结构为&#xff1a; {"message":"下载失败&#xff0c;下载文件不存在&#xff0c;请联系管理员处理&#xff01;","code":500} 2.vue 请求后台接口返回的 Blob数据 3.问题出现的原因是&#xff0c;正常其他数据列表接口&…

2024/4/2—力扣—连续数列

代码实现&#xff1a; 思路&#xff1a;最大子数组和 解法一&#xff1a;动态规划 #define max(a, b) ((a) > (b) ? (a) : (b))int maxSubArray(int* nums, int numsSize) {if (numsSize 0) { // 特殊情况return 0;}int dp[numsSize];dp[0] nums[0];int result dp[0];fo…

阿里云云效CI/CD配置

1.NODEJS项目流水线配置(vue举例) nodejs构建配置 官方教程 注意:下图的dist是vue项目打包目录名称,根据实际名称配置 # input your command here cnpm cache clean --force cnpm install cnpm run build 主机部署配置 rm -rf /home/vipcardmall/frontend/ mkdir -p /home/…

海山数据库(He3DB)原理剖析:浅析OLAP数据库计算引擎中的统计信息

背景&#xff1a; 统计信息在计算引擎的优化器模块中经常被提及&#xff0c;尤其是在基于成本成本优化&#xff08;CBO&#xff09;框架中统计信息发挥着至关重要的作用。CBO旨在通过评估执行查询的可能方法&#xff0c;并选择最有效的执行计划来提高查询性能。而统计信息则提…

传统企业如何实现数字化转型?

传统企业实现数字化转型是一个系统性工程&#xff0c;涉及到企业战略、技术应用、组织结构、业务流程、人才培养等多个方面。以下是一些关键步骤和策略&#xff1a; 1、明确转型目标和战略&#xff1a;首先&#xff0c;企业需要明确数字化转型的目标&#xff0c;这通常是为了提…

48-基于腾讯云EKS的容器化部署实战

准备工作 在部署IAM应用之前&#xff0c;我们需要做以下准备工作&#xff1a; 开通腾讯云容器服务镜像仓库。安装并配置Docker。准备一个Kubernetes集群。 开通腾讯云容器服务镜像仓库 在Kubernetes集群中部署IAM应用&#xff0c;需要从镜像仓库下载指定的IAM镜像&#xff…

MES车间管理有哪些方面

一、MES车间管理概述 MES车间管理是以MES系统为基础&#xff0c;对车间生产过程进行全方位、实时性的管理和控制。它涵盖了生产计划、生产调度、物料管理、设备维护、质量控制等多个方面&#xff0c;确保生产过程的顺利进行&#xff0c;提高生产效率和质量。 二、生产计划与调…

【重磅福利】数字化转型大数据数据治理平台建设精品PPT合集共25份(免费下载)

【1】关注本公众号 【2】私信发送 数字化转型 【3】获取本方案合集的下载链接&#xff0c;直接下载即可。 如需下载更多PPT原格式方案文档&#xff0c;请加入微信扫描以下方案驿站知识星球&#xff0c;获取上万份PPT解决方案&#xff01;&#xff01;&#xff01;感谢支持&am…

AI大模型探索之路-应用篇8:Langchain框架LangServe模块-专注于AI模型的部署

目录 前言 一、概述 二、功能特性 三、REST API 开发 四、Postman调用测试 五、Client调用测试 总结 前言 随着AI大语言模型&#xff08;LLM&#xff09;的技术的不断演进&#xff0c;AI应用的开发和部署变得越来越复杂。在这样的背景下&#xff0c;LangServe应运而生—…