基于动态规划的0-1背包问题学习

news2026/4/2 3:10:21

关于动态规划

动态规划是一种解决多阶段决策过程最优化问题的数学方法。其基本思想是将问题分解成若干个子问题,通过求解子问题的最优解来推导出原问题的最优解。

具体而言,动态规划方法可以分为两个步骤:

定义状态:将原问题转化为某一阶段的子问题,并记录下该子问题的最优解。

状态转移方程:通过对每个子问题的最优解进行组合,得到原问题的最优解。

在定义状态时,需要明确每个状态所代表的含义和与其他状态之间的关系;在构造状态转移方程时,需要根据前一个状态推出当前状态,从而不断递推到最终状态,得到最优解。

动态规划方法通常适用于具有“无后效性”、“最优子结构”和“重复子问题”的问题,因为这些问题可以被分解为若干个子问题,在每个子问题中使用相同的状态转移方程,从而获得全局最优解。同时,动态规划方法也可以通过记忆化搜索的方式实现,避免了重复计算子问题。因此,它在解决大规模的各种优化问题上具有广泛的应用价值。

0-1背包问题

背景

给定指定体积的背包,商品的体积和价值,商品不能切割单位化。每个商品要么选择装入背包,要么不装入.

思想

用二维数组f[i][j]来表示背包在决策前i个商品时,容量为j时的价值.
背包容量按升序遍历,f[i-1][j]理解为保存在不同容量下对前i-1个物体的决策的最优解(最大价值).
状态转移方程: f[i][j] =max(f[i-1][j],f[i-1][j-v[i]]+w[i]);

初始状态

当背包容量为0时,背包的价值为0.

解决方案

二维数组的方式

  #include "iostream"
   using namespace std;

 

   const int  MAXNUM = 1e3+10;


   int goods[MAXNUM][MAXNUM];
   int VS[MAXNUM];
   int WEX[MAXNUM];
   int main()
   {
       
       int N ,V;
       cin>>N>>V;
       for(int i = 1;i<=N ; i++)
       {
           int v,w;
           cin>>v>>w;
           VS[i]=v;
           WEX[i]=w;
           
       }
       
       for(int i = 1; i <= N ;i++)
       {
           for(int j = 1 ; j<=V;j++)
           {
               
               if(VS[i] > j)
               {
                   goods[i][j] = goods[i-1][j]; //不装
               }
               else
               {
                   goods[i][j]= max(goods[i-1][j],goods[i-1][j-VS[i]]+WEX[i]);//装
                   
               }
           }
       }
           cout<<goods[N][V];
       
       
       
   
   return 0;   
   }

一维优化逆序容量遍历+输入优化

    #include "iostream"
    using namespace std;

    #define MAXNUM 1000+10


    int f[MAXNUM];
    
    int main()
    {
        
        int N ,V;
        cin>>N>>V;
        for(int i = 1;i<=N ; i++)
        {
            int v,w;
            cin>>v>>w;
            
            for(int  j = V; j >= v;j--)
            {
                f[j] = max(f[j],f[j-v]+w);
            }
            
        }
        
    cout<<f[V];
        
        
    
    return 0;   
    }

关于为什么要容量逆序原因:

若使用正序遍历则在决策第i个物体时,比如计算f[7]需要用到f[4],而因为容量是按照正序进行遍历,可能f[4]已经被计算过了,这样在算f[7]时可能会被影响(比如多算了1次被决策的物体的价值)
简单来说,一维情况正序更新状态f[j]需要用到前面计算的状态已经被「污染」,逆序则不会有这样的问题。
为了加深理解,模拟过程:

    n=4 m=5//物品个数为4,背包总体积为5

    v[1]=1,w[1]=5;
    v[2]=2,w[2]=4
    v[3]=3,w[3]=4
    v[4]=4,w[4]=5

    for(int i=1;i<=n;i++)
    for(int j=m;j>=v[i];j--)
    if(j>=v[i]) f[j]=max(f[j],f[j-v[i]]+w[i]);

    01背包,逆序排列
    //依次判断每个物品
    //初始化全局定义f[N]=0
    i=1 j=5 此时j>=v[1]  f[5]=max(f[5],f[5-v[1]]+w[1])=max(f[5],f[4]+5)=5;//1
    i=1 j=4 此时j>=v[1]  f[4]=max(f[4],f[4-v[1]]+w[1])=max(f[4],f[3]+5)=5;//1
    i=1 j=3 此时j>=v[1]  f[3]=max(f[3],f[3-v[1]]+w[1])=max(f[3],f[2]+5)=5;//1
    i=1 j=2 此时j>=v[1]  f[2]=max(f[2],f[2-v[1]]+w[1])=max(f[2],f[1]+5)=5;//1
    i=1 j=1 此时j>=v[1]  f[1]=max(f[1],f[1-v[1]]+w[1])=max(f[1],5)=5;//1

    i=2,j=5 此时j>=v[2]  f[5]=max(f[5],f[5-v[2]]+v[2])=max(f[5],f[3]+4)=max(5,5+4)=9 //1 2
    i=2,j=4 此时j>=v[2]  f[4]=max(f[4],f[4-v[2]]+v[2])=max(f[4],f[2]+4)=max(5,5+4)=9 //1 2
    i=2,j=3 此时j>=v[2]  f[3]=max(f[3],f[3-v[2]]+v[2])=max(f[3],f[1]+4)=max(5,5+4)=9 //1 2
    i=2,j=2 此时j>=v[2]  f[2]=max(f[2],f[2-v[2]]+v[2])=max(f[2],f[0]+4)=max(5,4)=5 // 1

    i=3,j=5 此时j>=v[3] f[5]=max(f[5],f[5-v[3]]+v[3])=max(f[5],f[2]+4)=max(9,5+4)=9 //1+2 1+3
    i=3,j=4 此时j>=v[3] f[4]=max(f[4],f[4-v[3]]+v[3])=max(f[4],f[1]+4)=max(9,5+4)=9 //1+2 1+3
    i=3,j=3 此时j>=v[3] f[3]=max(f[3],f[3-v[3]]+v[3])=max(f[3],f[0]+4)=max(9,4)=9 //1+2
    ………//后续省略

    完全背包,正序排列

    n=4 m=5//物品个数为4,背包总体积为5
    v[1]=1,w[1]=5;
    v[2]=2,w[2]=4
    v[3]=3,w[3]=4
    v[4]=4,w[4]=5

    for (int i = 1; i <= n; i ++ )
            for (int j = v[i]; j <= m; j ++ )
                f[j] = max(f[j], f[j - v[i]] + w[i]);

    //判断第一个物体 这里的正序决策前面数据被影响
    i=1 j=1 此时j<m f[1]=max(f[1],f[j-v[1]]+w[1])=max(f[1],f[1-1]+5)=max(0,5)=5//1//一个1
    i=1 j=2 此时j<m f[2]=max(f[2],f[j-v[1]]+w[1])=max(f[2],f[2-1]+5)=max(0,5+5)=10//两个1
    i=1 j=3 此时j<m f[3]=max(f[3],f[j-v[1]]+w[1])=max(f[3],f[3-1]+5)=max(0,10+5)=15//三个1
    i=1 j=4 此时j<m f[4]=max(f[4],f[j-v[1]]+w[1])=max(f[4],f[4-1]+5)=max(0,15+5)=20//四个1
    i=1 j=5 此时j=m f[5]=max(f[5],f[j-v[1]]+w[1])=max(f[5],f[5-1]+5)=max(0,20+5)=25//五个1

    i=2 j=2 此时j<m f[2]=max(f[2],f[j-v[2]]+w[2]=max(f[2],f[2-1]+4)=max(10,5+4)=10//两个1
    i=2 j=3 此时j<m f[3]=max(f[3],f[j-v[2]]+w[2]=max(f[3],f[3-1]+4)=max(15,10+4)=15//三个1
    i=2 j=4 此时j<m f[4]=max(f[4],f[j-v[2]]+w[2]=max(f[4],f[4-1]+4)=max(20,15+4)=20//四个1
    i=2 j=5 此时j<m f[5]=max(f[5],f[j-v[2]]+w[2]=max(f[5],f[5-1]+4)=max(25,20+4)=25//五个1
    ………//后续省略

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序抓包

https://github.com/water-kid/WeChatOpenDevTools 抓包工具 第一次安装成功了&#xff0c;公众号能抓&#xff0c;&#xff0c;小程序报错&#xff0c;&#xff0c;卸载后安装不起了 方法二&#xff1a; 将version.dll 放入 微信所在目录 E:\Program Files\Tencent\WeChat\[…

SpringBoot 如何使用 Ehcache 作为缓存

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中&#xff0c;跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案&#xff0c;它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…

全息投影技术服务公司【盟云全息】收入急剧下降,存在风险

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 全息投影技术服务公司【盟云全息】MicroCloud Hologram(HOLO)的股价表现今年以来异常出色&#xff0c;年初至今已经上涨了334%以上&#xff0c;猛兽财经将在本文中分析MicroCloud Hologram股价上涨的原因&#xff0c;以及它…

Qt QGridLayout和QFormLayout案例分析

QGridLayout和QFormLayout是Qt中常用的布局管理器&#xff0c;可以用于在应用程序中设置控件的位置和大小。 QGridLayout网格布局(栅格布局) QGridLayout是一个网格布局管理器&#xff0c;可以将控件放置在一个二维网格中。在QGridLayout中&#xff0c;控件可以跨越多个行和列…

2023年中国涂料助剂市场发展历程及趋势分析:中高端助剂市场规模将会迎来新的增长[图]

涂料助剂又称油漆辅料&#xff0c;系配制涂料的辅助材料&#xff0c;能改进涂料性能&#xff0c;促进涂膜形成。种类很多&#xff0c;包括催干剂、增韧剂、乳化剂、增稠剂、颜料分散剂、消泡剂、流平剂、抗结皮剂、消光剂、光稳定剂、防霉剂、抗静电剂等&#xff0c;其中用量最…

2023年中国临床质谱检测行业市场规模及行业竞争格局分析[图]

临床质谱检测是指质谱技术在临床检验中的应用&#xff0c;主要涉及临床生化检验、临床免疫学检验、临床微生物检验以及临床分子生物诊断等多方面&#xff0c;质谱诊断比传统诊断技术更具灵敏性、特异性和准确性&#xff0c;且具有高通量、高效率和低成本的优势。临床质谱技术可…

Allegro 17.2如何直接更新元件封装?

想必很多从事电子设计的小伙伴&#xff0c;都有这样的经历&#xff1a;有些时候原理图和PCB设计是由不同的工程师负责&#xff0c;然后偶尔需要在没有原理图的情况下直接对PCB作品进行操作&#xff0c;如更新元件封装等操作&#xff0c;这种环节不仅费时费力&#xff0c;效率贼…

Table ‘mysql.proc‘ doesn‘t exist

使用workbench 同步model 報錯 "Table ‘mysql.proc‘ doesn‘t exist" 爲什麽會出現這個錯誤&#xff1f; 原因&#xff1a;误删了mysql数据库 解决办法如下&#xff1a; 1、在服务列表里找到mysql&#xff0c;停止服务 2、把mysql文件夹下的data文件夹备份&…

微信小程序--》从模块小程序项目案例23.10.09

配置导航栏 导航栏是小程序的门户&#xff0c;用户进来第一眼看到的便是导航栏&#xff0c;其起着对当前小程序主题的概括。而我们 新建的小程序 时&#xff0c;第一步变开始配置导航栏。如下&#xff1a; 配置tabBar 因为配置tabBar需要借助字体图标&#xff0c;我这里平常喜…

uniapp快速入门系列(3)- CSS技巧与布局

章节三&#xff1a;CSS技巧与布局 1. uniapp中的样式编写2. 常见布局技巧与实例解析2.1 水平居中布局2.2 垂直居中布局2.3 等高布局2.4 响应式布局 3. CSS动画与过渡效果 在uniapp中&#xff0c;我们使用CSS来设置页面的样式和布局。本章将介绍一些在uniapp中常用的CSS技巧和布…

区块链技术在金融领域的应用场景

区块链技术在金融领域具有广泛的应用场景&#xff0c;它可以提供更安全、透明、高效和可信的金融服务。以下是一些区块链金融的主要应用场景&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.数字货币…

多媒体播放软件 Infuse mac中文特点介绍

Infuse mac是一款多媒体播放器应用&#xff0c;它支持播放多种格式的视频文件、音频文件和图片文件&#xff0c;并且可以通过AIrPlay将媒体内容投放到其他设备上。Infuse还支持在线视频流媒体播放和本地网络共享&#xff0c;用户可以通过它来访问家庭网络上的媒体文件。 Infuse…

【elasticsearch】elasticsearch8.0.1使用rpm包安装并启用TLS

背景 公司的业务需要在加密的情况下使用&#xff0c;为此&#xff0c;研究测试了一下es8是如何启用TLS的。以下是测试使用过程。 x-pack了解 在 Elasticsearch 7.11.0 版本及更高版本中&#xff0c;X-Pack 功能在默认情况下已经整合到 Elastic Stack 的各个组件中&#xff0…

黑盒测试方法:原理+实战

目录 一、如何设计测试用例 二、黑盒测试常用方法 1、基于需求进行测试用例的设计 2、等价类 3、边界值 4、判定表分析法&#xff08;因果分析法&#xff09; 5、正交表 6、场景设计法 三、案例补充 1、使用Fiddler模拟弱网 2、针对一个接口该如何测试 一、如何设计测试…

低成本开发一款苹果ios安卓apk双端的APP应用制作用什么语言研发浅谈一些低代码平台

这不是很懂代码的同学们还是比较多的吧&#xff0c;公司想开发一款app不想成本增加太大&#xff0c;不知道怎么找团队做事情&#xff0c;找什么语言的呢&#xff1f;都是最后能组成一个app但是不知道从哪里下手可以看看兄弟我的这篇文章哈&#xff0c;虽然不是很厉害&#xff0…

区块链技术-比特币数据结构

背景 随着近几年区块链技术的迅速发展&#xff0c;越来越多的行业正在将区块链技术应用到实际中去。例如&#xff0c;金融、物流、交易所等行业都开始尝试使用区块链技术来替代传统技术。伴随着区块链迅速发展的期间&#xff0c;诞生了比特币&#xff08;BTC&#xff09;、以太…

深度学习DAY1:神经网络NN;二元分类

深度学习笔记 DAY1 深度学习基本知识 1.神经网络 1.1 单一神经元 所有神经元将房屋大小size作为输入x,计算线性方程&#xff0c;结果取max&#xff08;0&#xff0c;y&#xff09;,输出预测房价y ReLU函数&#xff08;线性整流函数&#xff09;–max&#xff08;0&#xf…

二叉树的层序遍历 --力扣

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

vue3中动态设置ref,如表格中使用级联选择器

需求&#xff1a;vue3中有一个表格&#xff0c;表格里是表单项&#xff0c;用户可以输入或选择&#xff0c;有一项是一个级联选择器&#xff0c;需要使用到ref&#xff0c;然后通过getCheckedNodes()方法获取到这一项选择的数据。 数据源是一个级联选择器&#xff0c;如果这个表…

c++视觉处理-----膨胀腐蚀

c视觉处理膨胀腐蚀 膨胀腐蚀的区别 膨胀&#xff08;Dilation&#xff09;和腐蚀&#xff08;Erosion&#xff09;是形态学图像处理中的两种基本操作&#xff0c;它们有不同的效果和应用&#xff1a; 膨胀&#xff08;Dilation&#xff09;&#xff1a; 膨胀操作用于增加物体…