一文读懂背包问题


转自:刘毅

https://www.61mon.com/index.php/archives/188/


问题展开


有 N 件物品和一个容量为 V 的背包。第 i 件物品的体积是 Ci,其价值是 Wi。求解,在不超过背包容量情况下,将哪些物品装入背包可使价值总和最大。


基本思路


这是最基础的背包问题,特点是:每种物品仅有一件。


状态 F[i,v] 表示前 i 件物品中选择若干件放在容量为 v 的背包中,可以取得的最大价值。


转移方程:



对于第 i 件物品,有放与不放两种选择。若选择不放,F[i,v]=F[i−1,v];若选择放,v−Ci 确保有足够的空间,随之 F[i,v]=F[i−1,v−Ci]+Wi。


代码展开


/**

 *

 * author 刘毅(Limer)

 * date   2017-03-17

 * mode   C++

 */

#include <iostream>

#include <algorithm>

using namespace std;

int main()

{

    const int N = 6;                     // 物品个数

    const int V = 10;                    // 背包体积

     // 第 i 个物品的体积(下标从 1 开始)

    int C[N + 1] = { -1,5,6,5,1,19,7 }; 

     // 第 i 个物品的价值

    int W[N + 1] = { -1,2,3,1,4,6,5 };   

     // 状态

    int F[N + 1][V + 1] = { 0 };        

    // 对于第 i 个物品

    for (int i = 1; i <= N; i++) 

        for (int v = 0; v <= V; v++)

        {

            F[i][v] = F[i - 1][v];  //第 i 个不放

            // 如果比它大,再放第 i 个

            if (v - C[i] >= 0 && F[i][v] < F[i - 1][v - C[i]] + W[i])                 

                   F[i][v] = F[i - 1][v - C[i]] + W[i];

        }

    cout<< F[N][V] << endl;  

    return 0;

}


以上方法的时间和空间复杂度均为 O(VN),其中时间复杂度应该已经不能再优化了,但空间复杂度却可以优化到 O(V)。


先考虑上面讲的基本思路如何实现,肯定是有一个主循环i ← 1 to N,每次算出来二维数组 F[i,v] 的所有值。


那么,如果只用一个数组 F[v] 能不能保证第 i 次循环结束后 F[v] 中表示的就是我们定义的状态 F[i,v] 呢?


F[i,v] 是由 F[i−1,v] 和 F[i−1,v−Ci] 两个子问题递推而来,能否保证在推 F[i,v] 时(也即在第 i 次主循环中推 F[v] 时)能够取用 F[i−1,v] 和 F[i−1,v−Ci] 的值呢?


事实上,这要求在每次主循环中我们以v ← V to C[i]的递减顺序计算 F[v],这样才能保证计算 F[v] 时 F[v−Ci] 保存的是状态 F[i−1,v−Ci] 的值。


优化后的代码如下:


/**

 *

 * author 刘毅(Limer)

 * date   2017-03-17

 * mode   C++

 */

#include <iostream>

#include <algorithm>

using namespace std;

int main()

{

    const int N = 6;                     // 物品个数

    const int V = 10;                    // 背包体积

    // 第 i 个物品的体积(下标从 1 开始)

    int C[N + 1] = { -1,5,6,5,1,19,7 };  

    // 第 i 个物品的价值

    int W[N + 1] = { -1,2,3,1,4,6,5 };  

    int F[V + 1] = { 0 };                // 状态

    for (int i = 1; i <= N; i++)  // 对于第 i 个物品

        for (int v = V; v >= C[i]; v--)

            F[v] = max(F[v], F[v - C[i]] + W[i]);

    cout << "最大价值是:" << F[V] << endl;  

    return 0;

}


初始化的细节问题


我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。有的题目要求 “恰好装满背包” 时的最优解,有的题目则并没有要求必须把背包装满。


这两种问法的实现方法只是在初始化的时候有所不同。


如果是第一种问法,要求恰好装满背包,那么在初始化时除了 F[0] 为 0,其它 F[1]...F[V] 均设为−∞,这样就可以保证最终得到的 F[V] 是一种恰好装满背包的最优解。


如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将 F[0]...F[V] 全部设为 0。


这是为什么呢?可以这样理解:初始化的 F 数组事实上就是在没有任何物品可以放入背包时的合法状态。


如果要求背包恰好装满,那么此时只有容量为 0 的背包可以在什么也不装且价值为 0 的情况下被 “恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,应该被赋值为 -∞了。


如果背包并非必须被装满,那么任何容量的背包都有一个合法解 “什么都不装”,这个解的价值为 0,所以初始时状态的值也就全部为 0 了。


参考文献


背包九讲。



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

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

相关文章

python核心数据类型_Python核心数据类型——列表

列表列表是任意对象的有序集合。也就是说&#xff0c;其元素可以是任何类型的对象。有序指的是&#xff0c;有严格的从左到右的顺序&#xff0c;这一点不同于字典&#xff0c;可以通过偏移读取&#xff0c;支持在原处修改&#xff0c;长度可变&#xff0c;是可变的类型。1. 常…

java io操作_Java 的IO操作(文件的读,写操作)

/* * FileEditor.java * * Created on 2006年9月13日, 下午2:22 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ /** *这是第一个类&#xff0c;没有利用缓冲技术 */ package fileeditor; import java.io.*;…

小米造车是智能手机进入红海后的突围之举

日前&#xff0c;媒体报道小米已确定造车&#xff0c;并视其为战略级决策。此前&#xff0c;雷静曾多次考虑造车&#xff0c;但未下定决心&#xff0c;而是选择了投资蔚来和小鹏&#xff0c;而且并未占多少股权&#xff0c;小米在两家公司上市时的持股份额均不到 5%&#xff0c…

linux服务之NIS

NIS服务RHEL4系统中NIS服务器软件的名称是ypserv&#xff0c;该软件包没有被系统默认安装&#xff0c;需要手动安装系统中的ypbind软件包是NIS客户端需要使用的软件包&#xff0c;yp-tools软件包中提供了对NIS服务器的查询和管理工具软件&#xff0c;这两个包是RHEL4系统中默认…

群论的创立:两个少年天才的接力

我们生活的世界中&#xff0c;美丽的对称无处不在。不过喜欢认死理的数学家&#xff0c;则硬要用他们独特的语言来定义对称。在数学上&#xff0c;对称与群相关联。随着数论、代数方程和几何等研究方向的发展&#xff0c;“群论”这个无比重要的数学领域被开创建立。而这一伟大…

python oracle连接池_【Python + Oracle】Python Oracle连接池—改进版

Oracle 连接池第四版。编程语言Python语言版本3.5.3实现功能oracle 连接池&#xff0c;解决频繁连接oracle数据库带来的连接资源耗费问题程序托管GitHub-OraclePool修改日期2020年8月3日version 4.0 改进说明&#xff1a;**[2020-04-21]** 修复连接用完后&#xff0c;不放回连接…

为什么有些大公司的技术弱爆了?

阅读本文大概需要5分钟。最近好几个大厂的读者不约而同跟我聊到公司采用的技术栈很落后的问题&#xff0c;一个读者还感叹&#xff1a;是不是大厂的领导都是混子&#xff1f;技术这么弱还不如之前呆的小公司。回复了几个读者朋友之后&#xff0c;这里也想跟大家分享下这个问题&…

普通程序员转型深度学习指南

AI领域人才奇缺&#xff0c;炙手可热的AI专业应届生年薪30万起步&#xff0c;AI毕业生基本不用找工作&#xff0c;都已经被企业早早预定。AI人才究竟有多紧缺&#xff1f;据腾讯研究院《全球人工智能人才白皮书》报告数据&#xff0c;目前全球AI领域人才仅约30万&#xff0c;全…

sm缩写代表什么意思_pe、PE在电气有代表什么意思,你发现没有,电气技术很有意思...

pe、pe、pe这些是什么意思解说1&#xff0c;听小课堂电小二跟你讲PE是Protecting Earthing的缩写&#xff0c;简体中文名称称之为“保护导体”&#xff0c;也就是我们通常所说的“地线”&#xff0c;我国规定PE线为黄绿双色线 。1.PE线的应用PE线是专门用于将电气装置外露导电部…

java短信接口 调用_带你了解短信接口的调用

查看接口说明image.png注册账号注册成功的页面如下&#xff1a;image.png设置短信内容的签名比如&#xff1a;将短信签名设置为yzcimage.png查取短信接口密钥image.png设计Java程序短信发送客户端的代码如下&#xff1a;package day02;import org.apache.http.Header;import or…

抢鲜体验.NET6 Preview1,配上Docker简直停不下来!

新年复工后的第一件大事儿就是上周三重磅发布的.NET6 Preview1&#xff0c;发布了很多的新特性&#xff0c;让人欢欣鼓舞&#xff01;然而有些小伙伴儿却担心学不过来了&#xff0c;其实不用担心的&#xff0c;照常用你的.NET5&#xff0c;等11月份.NET6 LTS正式发布了&#xf…

实用金属材料手册_机械密封选用手册

《机械密封选用手册》较系统地介绍了机械密封的原理、结构、材料及辅助系统装置及安装、使用方法和故障分析等。内容以产品样本图册为主&#xff0c;并做了相应的结构说明。本书重点介绍了机械密封的选用方法&#xff0c;读者可根据介质、温度、压力、转速等工况条件选取合适的…

为什么在人工智能火爆的现在,我们还在做数据分析

这些年来&#xff0c;随着进入大数据时代&#xff0c;各行各业均有一个词频频被提到&#xff0c;那就是数据分析。那么数据分析究竟是什么呢&#xff1f;数据分析就是指用适当的统计分析方法对收集来的大量数据进行处理分析&#xff0c;提取有用信息并形成结论&#xff0c;从而…

加入域--深入理解DNS在域中作用

接前面《创建windows域--深入理解域概念》这篇文章&#xff0c;来说说加入域的问题。 有人加入域时很顺利&#xff0c;几分钟甚至几秒的功夫&#xff0c;完毕。有人加入域时很恼火&#xff0c;折腾了一天甚至几天始终丈二和尚莫不找头脑。有个学生&#xff0c;很勤奋&#xff0…

学生成绩管理java代码_Java swing学生成绩管理系统

项目描述本系统主要分为5大功能模块&#xff0c;分别为&#xff1a;登录模块&#xff1a;实现用户登录。参数设置&#xff1a;包括学生年级设置、班级设置、考试科目设置以及考试类别设置。基本信息&#xff1a;包括学生信息、教师信息以及学生考试成绩信息管理。系统查询&…

你可能不知道的按位与、或运算技巧

背景最近在园子里看到了这篇文章&#xff0c;看完这篇会有意外收获&#xff1a;C#枚举高级战术https://mp.weixin.qq.com/s/yipaL6Acil-uxq_bDDgdyg想起了很久之前的自己的一篇总结&#xff0c;特地找出来说说概念在工作中遇到按位或组合权限串。一直不是特别明白。今天终于花了…

web高德地图怎么加载离线地图_怎么验证全国离线卫星地图缓存文件的完整性

1. 概述自从我们发布了《如何离线浏览全国7137GB海量谷歌卫星离线影像》一文后&#xff0c;很多用户都在问下载海量数据的具体方法&#xff0c;为了解决大家的困惑&#xff0c;于是又分别发布了《如何一次性下载全国谷歌卫星影像地图数据的方法》和《如何一次性下载谷歌地球的全…

为什么程序员发现不了自己的BUG?

最近在朋友圈流行了这样的一个小学数学题&#xff0c;当然结果是“出乎意料”&#xff0c;看似简单的结果&#xff0c;几乎很少有人做对&#xff0c;而分析下来的原因无非是惯性思维下的粗心导致的完全错误&#xff0c;今天小编就带大家一起分析下思考过程。看图可知&#xff0…

IP代理在网络游戏中的应用

前些天同学开了打钱工作室&#xff0c;想玩外服魔兽打点游戏B赚点钱&#xff0c;可是不会上外国魔兽&#xff0c;叫我帮忙给看看怎么才能玩外服。现在我就来做个简单的教程&#xff0c;说明一下怎么玩外服吧。先说明一些现状&#xff1a;一些海外网络游戏服务器和带宽资源有限&…

python游戏代码运行不了_无法使我的tic tac toe游戏在python中正确运行

转不到“玩家1”的原因是你的支票中缺少一个空格。你也没有正确地检查一个玩家何时获胜,这就是为什么你会有这种奇怪的行为。你需要检查每个位置,而不仅仅是最后一个。我还添加了对用户输入的检查,以确保用户输入的是一个数字,如果不是,它不会崩溃。我完全不明白为什么你基本上…