满篇都是干货,有详细的注释和代码,请放心观看。

这就是传说中的 01 背包问题,这个问题看到之后主要有两种思路:

一、贪心做法(错误想法)

这道题如果没有学过 01 背包问题的话,很容易想成一个贪心的问题,就是讲他的 “性价比"
 从高到低排序(这里的“性价比”指的是  ),但是我们很容易发现这是错误的,因为将性价比较高的放在前面的话那么不可以尽量的吧空间占用完,所以我们可以显然的发现,这样的方法是错误的,但是如果题目的数据比较水的话还是可以骗很多分的。。

所以这种做法是错误的。

二、01背包问题做法(朴素版本)

01 背包问题基本上是十分常见的 DP 问题。

我们通过普通的做 DP 的思路,得先想想应该怎么定义 DP 的状态,我们应该怎么做呢?

第一步:

通过以往做 DP 的经验,那么可以不是很困难的得出定义 : 为选取前  个物品,使得总重量不超过  的最大总价值(这个是很重要的点,如果在做动态规划的时候没有想出这个点,那么基本上这道题就没有什么希望了)。

第二步:

这个 DP 数组是否需要加初始化,但是是否定的,因为这道题的 数组一直都在不断的更新,所以这里也不会溢出或者判断错误,可以得出结论:这里的   数组不需要初始化!

        第三步:

第三步是最难的一步,也是我主要要讲的一步,这一步就是支撑整个代码的“顶梁柱”,那就是:状态应该怎么转移呢

其实可以发现:枚举每个物品,比如当前枚举到了第 i 个物品,可以发现一共有两种情况:
        一、不选第 i 个物品,那么

二、选第 i 个物品,那么可以发现

首先解释一下第一种:就是如果不选第  个物品,那么其实和只选前  个物品一样,都是一样的价值,所以可以的出以上表达式。

解释一下第二种的理解:在前 i-1 个物品中,是总重量不超过 j-v[i] (因为当前枚举到了第 i 个物品,总重量为 j,当前的物品重量为 v[i] ,所以可以发现当前的重量就不可以超过 j-v[i]),所以答案不就呼之欲出了。。(注意最后要加上当前这个物品的总价值)

总结一下:这道题的状态转移方程式是:

然后这里还要注意一个点,就是在  的时候有可能会出现负下标,所以需要特判一下 ,这就是一个推导状态转移方程式的一个简单的解析,所以就可以写出以下代码(代码中也有较为详细的解释,我在这里就不多说了):

/*f[i][j] = f[i-1][j-v[i]]+w[i]
价值等于前i-1个物品的总容量不超过(j-v[i])的总价值
j-v[i]的含义:最大的容量为j,然而要放进i这个物品,i物
品的重量为v[i],所以前i-1个物品的最大容量只能是(j-v[i])。*/#include <iostream>
#include <algorithm>using namespace std;
const int N = 1010;int n, m;//m就是题目中的v
int v[N], w[N], f[N][N];int main(){scanf("%d%d", &n, &m);for(int i = 1; i <= n; i ++ ) scanf("%d%d",&v[i],&w[i]);for(int i = 1; i <= n; i ++ )for(int j = 0; j <= m; j++){f[i][j] = f[i-1][j];if(j >= v[i]) f[i][j] = max(f[i][j], f[i-1][j-v[i]]+w[i]);}printf("%d\n", f[n][m]);return 0;
}

三、01背包问题做法(一维数组优化版本)

这种方法会讲的稍微快一点,因为这种方法就是思路二的一个优化版本,所以建议可以先把思路二的想法先看懂,然后再看这里的解析。

还是熟悉的 DP 三部曲:

第一步:

依旧是定义 DP 数组,这里定义成一维的数组,那么就可以轻易的定义出: dp[i] 表示不超过 i 的最大总价值。

第二步:

这个 DP 数组是否需要初始化,也就是说他会不会超出边界或者得到不正确的答案,可以简单的画图模拟一下,发现是明显不会覆盖或超出边界的,所以这里的 DP 数组依旧不需要初始化。

第三步:

这里我依旧要特别重要的讲一下,其实可以发现不论是二维数组还是一维数组,他们的状态转移其实都是差不多的,所以其实可以直接将上面推出来的那一个状态转移方程给移动到下面来。

二维数组的状态转移:,那么一维数组就可以在二维数组的基础上进行“直接去掉一维”的操作,所以可以得出一维数组的状态转移方程式:,其实在这里不是很好说明它是对的,所以这里我给大家举一个例子:

比如这里输入三个物品和一个容量为  的背包,他们的  分别是分别是.

然后可以自己尝试一下,发现其实这个答案是错误的。

为什么是错误的呢?

其实,并不是状态转移方程错了,而是循环的顺序错了,应该把循环反过来,才可以保证它的正确性,只要稍微想一下可以发现确实如此,因为从后往前进行查找,才不会出现错误的、或者重复的情况,从而就保证了现在这种策略的准确性。

然后给出参考代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>using namespace std;const int N = 1010;
int n, m, v[N], w[N], f[N];int main(){scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) scanf("%d%d", &v[i], &w[i]);for(int i = 1; i <= n; i++)for(int j = m; j >= v[i]; j--){/*注意:这里的循环变量要从0开始,因为
这里的这个j表示的是价值不超过j,所以j可以是0*/f[j] = max(f[j], f[j-v[i]]+w[i]);//我们可以发现每次f[j]数组都要依靠前一个,但是这里明显反了,所以要把循环倒过来}printf("%d\n", f[m]);return 0;
}

其实,有些时候也是不可以进行一维数组的优化的,比如:LTS问题。

注1:在上面给出的两则代码中我在文章中所写的 dp 函数我都用的是 f 函数代替,如有观看的效果不佳,可以乱喷。

谢谢大家支持,这是我的第一篇 CSDN 中的 DP 博客,如果有阅读的不便或者手滑错误请谅解,并且私信/在评论区指出,我会第一时间改进的!!!

觉得博主写的不错的关注支持一下吧!我会继续努力的~

动态规划之01背包问题相关推荐

  1. 0-1背包问题 动态规划java_C#使用动态规划解决0-1背包问题实例分析

    // 利用动态规划解决0-1背包问题 using System; using System.Collections.Generic; using System.Linq; using System.T ...

  2. 经典动态规划:0-1 背包问题

    经典动态规划:0-1 背包问题 文章目录 经典动态规划:0-1 背包问题 一.题目描述 二.动规标准套路 三.题目描述 四.解法分析 五.优化 一.题目描述 就讨论最常说的 0-1 背包问题,简单描述 ...

  3. 动态规划解决0-1背包问题详解(图文并茂)

    动态规划解决0-1背包问题 这个是网上比较好的案例,因为原文有些地方晦涩难懂,对于刚接触动态规划问题的朋友来说很不友好,所以很对地方加入了我自己的见解,也是作为我的一次学习历程. 一.问题描述: 有n ...

  4. 背包问题动态规划matlab,01背包问题动态规划详解

    计算机算法分析考试:动态规划0-1背包问题,怎么算她说她没醉,却一直摇摇晃晃掉眼泪:你说你爱她,却从未想过给她一个家. 要考试了,老师给划重点有一题:动态规划0-1背包问题,怎么算. 怎么理问题描述: ...

  5. o-1背包问题迭代_经典动态规划:01背包问题的变体

    点击上方蓝字设为星标 东哥带你手把手撕力扣~ 作者:labuladong   公众号:labuladong 若已授权白名单也必须保留以上来源信息 上篇文章 经典动态规划:0-1 背包问题 详解了通用的 ...

  6. 三十四、动态规划解决01背包问题

    一.动态规划算法介绍 动态规划算法的核心思想是:将大问题划分为小问题进行解决,从而一步一步获取最优解的处理算法. 动态规划算法与分治算法类似,其基本思想是将待求解的问题分解成若干个子问题,先求子问题, ...

  7. 算法导论——动态规划:0-1背包问题(完全解)

    2019独角兽企业重金招聘Python工程师标准>>> package org.loda.dynamic;import org.junit.Test;/*** * @ClassNam ...

  8. 动态规划专题 01背包问题详解【转】

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

  9. 算法题解:动态规划解0-1背包问题

    概述 背包问题(Knapsack problem)是一种组合优化的NP完全问题.问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高.问 ...

  10. 【动态规划】01背包问题

    01背包问题 问题描述 给定 N 种物品和一个最大载重量为 C 的背包,物品 i 的重量是 wi,其价值为 vi . 问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大? 问题分析 对于 ...

最新文章

  1. oracle cluster n,10g Rac的cluster_interconnect信息
  2. python代码用c语言封装_树莓派开发ADC芯片CS1237(C语言和python库开发)
  3. mpvue外卖小程序
  4. Web容器启动中执行某个Java类
  5. MySQL---表操作
  6. Android App“加固”
  7. 做一个简单的网上交易系统(参考淘宝、天猫的交易系统)
  8. 【开源】.Net Api开放接口文档网站
  9. 微软2008系列 (Orcas + Longhorn Server+SQL2008)将于2008年2月27日发布
  10. 论文浅尝 | DRUM:一种端到端的可微的知识图谱上的规则学习方法
  11. java标识符命名_Java标识符命名规则
  12. Spring MVC之基于xml配置的web应用构建
  13. 某网站前端页面性能测试
  14. html中给select下拉框赋值
  15. GitHub上有不错的 C 开源项目?
  16. java gui即时聊天工具
  17. Ubuntu下pycharm设定任务栏图标后打开出现问号图标
  18. 计算机硬盘怎么整理,w7怎么整理磁盘碎片_如何清理win7电脑磁盘碎片
  19. Java中将String类型依照某个字符分割成数组
  20. 大型web系统数据缓存设计

热门文章

  1. 【聚类之DBSCAN】DBSCAN实例
  2. 希望计算机专业同学都知道这些宝藏博主
  3. 2021旗舰机选购指南
  4. c语言报错(二)expected initializer before “int“
  5. gitbook 使用粘自csdn
  6. PCDN服务接入实操手册
  7. 【Java开发语言 01】第一章 Java语言概述(基础常识+Java语言概述+Java程序运行机制及运行过程+Java语言环境的搭建+开发体验hello world+错误:编码GBK的不可映射字符)
  8. 08.甲流疫情死亡率
  9. 自媒体怎么赚钱?自媒体的5大变现方式!
  10. 没迈过PRA的门槛 企业谈何“人工智能”