【动态规划】01背包问题——算法设计与分析

这篇具有很好参考价值的文章主要介绍了【动态规划】01背包问题——算法设计与分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、问题定义

1.1 实例引入

若超市允许顾客使用一个体积大小为13的背包,选择一件或多件商品带走,则如何选择可以使得收益最高?

商品 价格 体积
啤酒 24 10
汽水 2 3
饼干 9 4
面包 10 5
牛奶 9 4

1.2 形式化定义

0-1 Knapsack Problem

输入:

\quad - n n n个商品组成集合 O O O,每个商品有属性价格 p i p_i pi和体积 v i v_i vi

\quad - 背包容量为 C C C

输出:

\quad - 求解一个商品子集 S ⊆ O S\subseteq O SO,使得

\quad \quad 优化目标: m a x ∑ i ∈ S p i max\sum_{i \in S}p_i maxiSpi

\quad \quad 约束条件: ∑ i ∈ S v i ≤ C \sum_{i \in S}v_i\leq C iSviC



二、问题求解

2.1 蛮力枚举

很自然的想法便是将所有商品一一列举出来,然后将不符合容量限制的组合去掉,在剩余中找到最大值,即为最优方案。

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

定义递归函数:

K n a p s a c k S R ( h , i , c ) KnapsackSR(h, i, c) KnapsackSR(h,i,c)

表示在第 h h h个到第 i i i个商品中,容量为 c c c时的最优解

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

例如,

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

我们可以发现如下的递推式:
K n a p s a c k S R ( h , i , c ) = m a x { K n a p s a c k S R ( h , i − 1 , c − v i ) + p i , K n a p s a c k S R ( h , i − 1 , c ) } KnapsackSR(h,i,c)=max\left \{ KnapsackSR(h,i-1,c-v_i)+p_i, KnapsackSR(h,i-1,c) \right \} KnapsackSR(h,i,c)=max{KnapsackSR(h,i1,cvi)+pi,KnapsackSR(h,i1,c)}
为了方便,将函数修改为

K n a p s a c k S R ( i , c ) KnapsackSR(i, c) KnapsackSR(i,c)

表示在前 i i i个商品中,容量为 c c c时的最优解

观察其递归树,我们会发现存在大量重叠子问题:

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

那么如何进一步优化以减少计算量?接下来引入带备忘录的递归。


2.2 带备忘递归

只需构造备忘录 P [ i , c ] P[i,c] P[i,c],表示在前 i i i个商品中选择,背包容量为 c c c时的最优解。

此时的递归树便可以被优化至下图所示:

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

给出其伪代码:

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

那么我们是否可以不进行递归,直接求解 P [ i , c ] P[i,c] P[i,c]?答案是肯定的,接下来使用动态规划来解决此问题。


2.3 动态规划

是否还记得我们之前发现的递推式?
K n a p s a c k M R ( i , c ) = m a x { K n a p s a c k M R ( i − 1 , c − v i ) + p i , K n a p s a c k M R ( i − 1 , c ) } KnapsackMR(i,c)=max\left \{ KnapsackMR(i-1,c-v_i)+p_i, KnapsackMR(i-1,c) \right \} KnapsackMR(i,c)=max{KnapsackMR(i1,cvi)+pi,KnapsackMR(i1,c)}
(1)首先,对备忘录进行初始化:

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

接着,根据递推式,确定计算顺序:

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

(2)于是,我们根据子问题的依赖关系,确定按照从左到右,从上到下的顺序进行计算。此时最优解出现在备忘录 P P P的右下角。

并且,为了记录选择了哪些商品,我们再引入一个 R e c Rec Rec数组,用来记录决策过程
R e c [ i , c ] = { 1 选择第 i 个商品 0 不选第 i 个商品 Rec[i,c]=\left\{\begin{matrix} 1 & 选择第i个商品\\ 0 &不选第i个商品 \end{matrix}\right. Rec[i,c]={10选择第i个商品不选第i个商品
根据上述关系式,最终可以求解出 P [ i ] [ c ] P[i][c] P[i][c] R e c [ i ] [ c ] Rec[i][c] Rec[i][c]

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

(3)根据 R e c [ i ] [ c ] Rec[i][c] Rec[i][c]数值,逆向搜索追踪最优解。

例如, R e c [ 5 ] [ 13 ] = 1 Rec[5][13]=1 Rec[5][13]=1,那么则选择了商品5,观察 R e c [ 5 − 1 ] [ 13 − v 5 ] = R e c [ 4 ] [ 9 ] = 1 Rec[5-1][13-v_5]=Rec[4][9]=1 Rec[51][13v5]=Rec[4][9]=1,则确定选择了商品4。

如此,最终可以得知选择了商品5,4,3。

其伪代码分为三部分:

①初始化 P [ i ] [ c ] P[i][c] P[i][c] R e c [ i ] [ c ] Rec[i][c] Rec[i][c]

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

②依次计算子问题,记录决策过程

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

③追踪最优方案

0-1背包问题动态规划算法伪代码,算法设计与分析,算法,动态规划

最终可以达到时间复杂度: O ( n C ) O(nC) O(nC),线性时间即可求解。



三、动态规划小结

实际上,带备忘递归和递推求解都叫做动态规划,他们的共同点都是分解问题来寻找关系,但是带备忘递归是自顶向下,而递推求解是自底向上,更加高效。

动态规划一般分为4步:

(1)分析问题结构

给出问题的形式化定义,明确原始问题。

分析问题的最优子结构,只有具有最优子结构性质和重叠子问题的问题才可以使用动态规划来进行求解。

最优子结构性质

①问题的最优解由子问题最优解组合而成

②子问题可以独立求解

(2)建立递推关系

(3)自底向上计算

(4)追踪最优方案文章来源地址https://www.toymoban.com/news/detail-756647.html

到了这里,关于【动态规划】01背包问题——算法设计与分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法学习17-动态规划01:背包问题

    提示:以下是本篇文章正文内容: 提示:这里对文章进行总结: 💕💕💕

    2024年04月27日
    浏览(30)
  • 湘潭大学 算法设计与分析实验 回溯 动态规划 贪心 模拟退火解决背包问题

    https://download.csdn.net/download/SQ_ZengYX/88620871 测试用例

    2024年02月02日
    浏览(44)
  • 01背包问题----动态规划 -----python代码、优化

    问题描述: 容量为C的背包选择装物品,有n个物品,它们有各自的体积wi和价值vi,如何让背包里装入的物品具有最大价值? 解题思路: 也就是n个物品选择装入背包,每个物品都有两种选择,是(1)或否(0), 建模:       xi表示当前第i个物品是否选择,xi取值为(0,1)

    2024年02月04日
    浏览(38)
  • 【Java实现】动态规划算法解决01背包问题

    1、问题描述: 一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大? 2、动态规划算法的概述 1)动态规划(Dynamic Progra

    2023年04月09日
    浏览(32)
  • 算法套路十四——动态规划之背包问题:01背包、完全背包及各种变形

    如果对递归、记忆化搜索及动态规划的概念与关系不太理解,可以前往阅读算法套路十三——动态规划DP入门 背包DP介绍:https://oi-wiki.org/dp/knapsack/ 0-1背包:有n个物品,第i个物品的体积为w[i],价值为v[i],每个物品至多选一个, 求体积和不超过capacity时的最大价值和,其中i从

    2024年02月10日
    浏览(36)
  • C++算法初级11——01背包问题(动态规划2)

    辰辰采药 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时

    2024年02月02日
    浏览(31)
  • 【算法日志】动态规划刷题:01背包问题,多重背包问题(day37,day38)

    目录 前言 目标和(01背包) 一和零(01背包) 零钱兑换(多重背包) 排列总和(多重背包) 这两天都是背包问题,其中的01背包的一些应用问题需要一定的数学建模能力,需要i将实际问题简化成我们熟悉的背包问题;而这两天的多重背包问题还算比较基础,但也要我明白了

    2024年02月11日
    浏览(33)
  • 动态规划01背包问题-代码随想录-刷题笔记

    有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品只能用一次 ,求解将哪些物品装入背包里物品价值总和最大。 二维dp数组01背包 确定dp数组以及下标的含义 是使用二维数组,即 dp[i][j] 表示从下标为[0-i]的物品里任意取,

    2024年02月07日
    浏览(30)
  • 【算法|动态规划 | 01背包问题No.2】AcWing 423. 采药

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【AcWing算法提高学习专栏】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成

    2024年02月06日
    浏览(33)
  • 力扣算法刷题Day42|动态规划:01背包问题 分割等和子集

    力扣题目:01背包问题(二维数组) 刷题时长:参考题解 解题方法:动态规划 + 二维dp数组 复杂度分析 时间 空间 问题总结 理解递推公式困难 本题收获 动规思路:两层for循环,第一层i遍历物品,第二层j枚举背包容量以内所有值 确定dp数组及下标的含义:dp[i][j] 表示从下标

    2024年02月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包