热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Leetcode题解动态规划01背包(1):问题简介

0-1背包有一个容量为N的背包,要用这个背包装下物品的价值最大,这些物品有两个属性:体积w和价值v。定义一个二维数组dp存储最大价值&
0-1 背包

有一个容量为 N 的背包,要用这个背包装下物品的价值最大,这些物品有两个属性:体积 w 和价值 v。

定义一个二维数组 dp 存储最大价值,其中 dp[i][j] 表示前 i 件物品体积不超过 j 的情况下能达到的最大价值。设第 i 件物品体积为 w,价值为 v,根据第 i 件物品是否添加到背包中,可以分两种情况讨论:

  • 第 i 件物品没添加到背包,总体积不超过 j 的前 i 件物品的最大价值就是总体积不超过 j 的前 i-1 件物品的最大价值,dp[i][j] = dp[i-1][j]。
  • 第 i 件物品添加到背包中,dp[i][j] = dp[i-1][j-w] + v。

第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。因此,0-1 背包的状态转移方程为:

 

dp[i][j] = value dp[i - 1][j - w] + v;

public int knapsack(int W, int N, int[] weights, int[] values) {int[][] dp &#61; new int[N &#43; 1][W &#43; 1];for (int i &#61; 1; i <&#61; N; i&#43;&#43;) {int w &#61; weights[i - 1], v &#61; values[i - 1];for (int j &#61; 1; j <&#61; W; j&#43;&#43;) {if (j >&#61; w) {dp[i][j] &#61; Math.max(dp[i - 1][j], dp[i - 1][j - w] &#43; v);} else {dp[i][j] &#61; dp[i - 1][j];}}}return dp[N][W];
}

public int knapsack(int W, int N, int[] weights, int[] values){int[][] dp &#61; new int[N&#43;1][W&#43;1];for(int i&#61; 1; i<&#61;N; i&#43;&#43;){int w &#61; weights[i-1], v&#61; vlaues[i-1];for(int j&#61;1; j<&#61;W; j&#43;&#43;){if(j >&#61; w){dp[i][j] &#61; Math.max(dp[i-1][j], dp[i-1][j-w] &#43; v);elsedp[i][j] &#61; dp[i-1][j];}}}return dp[N][W];
}

空间优化

在程序实现时可以对 0-1 背包做优化。观察状态转移方程可以知道&#xff0c;前 i 件物品的状态仅与前 i-1 件物品的状态有关&#xff0c;因此可以将 dp 定义为一维数组&#xff0c;其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此时&#xff0c;

 

因为 dp[j-w] 表示 dp[i-1][j-w]&#xff0c;因此不能先求 dp[i][j-w]&#xff0c;以防将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w]&#xff0c;在程序实现时需要按倒序来循环求解。

public int knapsack(int W, int N, int[] weights, int[] values) {int[] dp &#61; new int[W &#43; 1];for (int i &#61; 1; i <&#61; N; i&#43;&#43;) {int w &#61; weights[i - 1], v &#61; values[i - 1];for (int j &#61; W; j >&#61; 1; j--) {if (j >&#61; w) {dp[j] &#61; Math.max(dp[j], dp[j - w] &#43; v);}}}return dp[W];
}

public int knapsack(int W, int N, int[] weights, int[] values){int[] dp &#61; new int[W&#43;1];for(int i&#61;1; i<&#61;N; i&#43;&#43;){int w &#61; weights[i-1], v&#61; values[i-1];for(int j&#61;W; j>&#61;1; j--){if(j >&#61; w)dp[j] &#61; Math.max(dp[j], dp[j-w] &#43; v);}}
}

无法使用贪心算法的解释

0-1 背包问题无法使用贪心算法来求解&#xff0c;也就是说不能按照先添加性价比最高的物品来达到最优&#xff0c;这是因为这种方式可能造成背包空间的浪费&#xff0c;从而无法达到最优。考虑下面的物品和一个容量为 5 的背包&#xff0c;如果先添加物品 0 再添加物品 1&#xff0c;那么只能存放的价值为 16&#xff0c;浪费了大小为 2 的空间。最优的方式是存放物品 1 和物品 2&#xff0c;价值为 22.

idwvv/w
0166
12105
23124

变种


  • 完全背包&#xff1a;物品数量为无限个

  • 多重背包&#xff1a;物品数量有限制

  • 多维费用背包&#xff1a;物品不仅有重量&#xff0c;还有体积&#xff0c;同时考虑这两种限制

  • 其它&#xff1a;物品之间相互约束或者依赖


推荐阅读
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文介绍了Java数组的定义、初始化和多维数组的用法。通过动态初始化和静态初始化两种方式来初始化数组,并讨论了数组的内存分配和下标的特点。同时详细介绍了Java二维数组的概念和使用方法。 ... [详细]
author-avatar
风让我离开
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有