算法笔记(c++)--经典01背包问题


算法解释起来太抽象了。也不是很好理解,最好的办法就是一步步写出来。

背包问题的核心在于m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i])这个公式理解起来还是有点麻烦的特别我这种脑子笨的人。所以我先上段代码,然后那数据一步步分析就行了。

先上代码:代码稍微看看就行了,关键我下面的解释,走一遍就懂了。

#include <iostream>
#include<algorithm>
using namespace std;
const int N=;//假设物品最多个数
int v[N]={,,,,,,}; //价格
int w[N]={,,,,,,}; //体积 int main()
{
int m[N][N]={}; //m[i][j]数组代表在第i件物品,背包容量为j时候能获得最大的价值
int n=,c=;//设物品个数为6,背包容量为12
for(int i=;i<=n;i++) //遍历物品个数
{
for(int j=;j<=c;j++)//各种容量情况
{
if(j>=w[i])//若此时背包容量大于当前物品重量
//这里的m[i-1][j]就是第i-1个物品在j容量下的价值
//m[i-1][j-w[i]]这就是i-1个物品时候,背包容量为j-w[i]时候的最大价值
m[i][j]=max(m[i-][j],m[i-][j-w[i]]+v[i]);
else//背包容量小于当前物品重量
m[i][j]=m[i-][j];//维持第i-1个物品时候的背包重量
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=c;j++)
{
cout<<m[i][j]<<' ';
}
cout<<endl;
}
return ;
}

先解释下m[i][[j]的含义就是在i种物品的情况下,包容量为j的情况下,包内的最大价值。

另外:这里的价值和体积一开始用00这是自己先加上去的,因为公式里面有个m[i-1][j],当i=1的时候m[0][j]就是当0种物品时候不管j等于多少肯定是0啦。

好了接下来按照代码顺序来走一遍,走一遍就明白了。先上下数据表

体积 价值
0 0
4 8
6 10
2 6
2 3
5 7
1 2

我们代码中设置的物品个数为6,背包容量为12

m设[N][N]   N其实应该是max(物品个数,背包容量)。但是设大点又没事。

然后先开始遍历我接下来用(x,y)来代替m[i][j]了。

按照上面代码遍历顺序。

当0种物品或者0背包容量时候毫无疑问总价值为0---->所以(0,j)=0并且(i,0)=0


1)当0号物品,和一号物品的情况下

当物品仅有编号为1号物品的时候,背包容量为1的时候,此时判断当前背包容量是否大于1号物品的体积。

可以看见一号物品的体积为4,于是维持(i-1,j)也就是(0,1)时候的价值0;

同理我们一直到背包容量为3的时候,都是小于1号物品的体积的,所以都等于自己(i-1,j)时候包内的价值,所以都是0。

这样(1,1)(1,2)(1,3)都是0

当道(1,4)就不一样了这时候1号物品的体积等于了包的容量。这时候我们就想放进去。

怎么判断放不放呢?我们先给我们的背包腾出4个空间,看看腾出4个体积情况下包的价值是多少。然后把1号物品放进去和之前(0,4)比较下就好了。

看下公式(i,j)=max((i-1,j),(i-1,j-1号物品的体积)+1号物品的价值);

这样就简单明了啦,i-1的意思就是不算当前物品,或者说是前i-1个物品的情况下。

         j-w[i]的意思就是当前背包容量减去当前物品

         于是(i-1,j-1号物品的体积)+1号物品的价值)就是腾出4个体积后放入物品1后的价值,这个值为一号物品的价值8

         很明显,8>0,所以(1,4)=8

接下来4-12同样,不过只有物品1所以妥妥的都是8于是(1,4)(1,5)......(1,12)都是8


2)当有0,1,2号物品的情况下

首先(2,0)=0这没啥毛病

(2,1)时候,背包容量小于当前2号物品体积,所以=0;(2,1)(2,2)(2,3)都是

当(2,4)时候有了变化,(2,4)依然小于当前2号物品体积,所以这时候我们用(1,4)时候,(1,4)代表有0和1号物品时候的包内最大价值,我们在上面已经算出来了是8,于是(2,4)=8;

同理一直到(2,5)还是8.

但是当(2,6)这时候包已经可以放下2了,我们就给2号物品腾出6个空间把2号物品放进去,腾出6个空间后,现在2还没有放进去于是(1,0)=0,现在把二放进去就是(2,6)+2号物品的价值10

因为(1,6)=8<10所以(2,6)=10

同理,(2,7)...(2,9)都是10了

当(2,10)时候这时候又发送变化了,我们再给2号腾出6个空间发现(1,4)=4居然可以放下了,于是我们再把2号物品一起装到包里。就变成了(2,10)=18;

通过这两个例子应该很清楚了

下面我打印下结果看下是不是这样:

看见了把没毛病。确实和我解释的一样,那么下面的也都是这样了,最后要获取最大的价值。直接m[6][12]=24就行了。

总之最关键的就是那句话

m[i][j]=max(m[i-1][j],m[i-1][j-w[i]+v[i]])

但是理解了还不够,最好自己推演一遍,我觉得这是掌握疑难最好的办法。

就脑子里面想想会漏掉很多细节,推演一遍就可以真正懂。

算法笔记(c++)--01背包问题的更多相关文章

  1. 201871030108-冯永萍 实验二 个人项目— D{0-1}背包问题项目报告

    项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/2018CST 这个作业要求链接 https://www.cnblogs.com/nwnu-dai ...

  2. 201871030127-王明强 实验二 个人项目—《D{0-1}背包问题 》项目报告

    项目 内容 课程班级博客链接 班级博客 这个作业要求链接 作业要求 我的课程学习目标 (1)详细阅读<构建之法>学习并掌握PSP的具体流程(2)掌握背包问题,通过查阅相关资料,设计一个采用 ...

  3. 201871030118-雷云云 实验二 个人项目—D{0-1}背包问题项目报告

    项目 内容 课程班级博客链接 班级博客 这个作业要求链接 作业链接 我的课程学习目标 1.了解并掌握psp2.掌握软件项目个人开发流程3.掌握Github发布软件项目的操作方法 这个作业在哪些方面帮助 ...

  4. 201871010129-郑文潇 实验二 个人项目—《D{0-1}背包问题 》项目报告

    项目 内容 课程班级博客链接 课程链接 这个作业要求链接 [作业要求](https://www.cnblogs.com/nwnu-daizh/p/14552393.html) 我的课程学习目标 1.掌 ...

  5. 201871030138-杨蕊媛 实验二 个人项目—《D{0-1}背包问题》项目报告

    项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/2018CST 这个作业要求链接 https://www.cnblogs.com/nwnu-dai ...

  6. 算法笔记(c++)--完全背包问题

    算法笔记(c++)--完全背包和多重背包问题 完全背包 完全背包不同于01背包-完全背包里面的东西数量无限 假设现在有5种物品重量为5,4,3,2,1  价值为1,2,3,4,5  背包容量为10 # ...

  7. 算法笔记(c++)--关于01背包的滚动数组

    算法笔记(c++)--关于01背包的滚动数组 关于01背包问题:基本方法我这篇写过了. https://www.cnblogs.com/DJC-BLOG/p/9416799.html 但是这里数组是N ...

  8. python实现算法: 多边形游戏 数塔问题 0-1背包问题 快速排序

    去年的算法课挂了,本学期要重考,最近要在这方面下点功夫啦! 1.多边形游戏-动态规划 问题描述: 多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形.每个顶点被赋予一个整数值, 每条边被 ...

  9. 【优化算法】变邻域搜索算法解决0-1背包问题(Knapsack Problem)代码实例 已

    01 前言 经过小编这几天冒着挂科的风险,日日修炼,终于赶在考试周中又给大家更新了一篇干货文章.关于用变邻域搜索解决0-1背包问题的代码.怎样,大家有没有很感动? 02 什么是0-1背包问题? 0-1 ...

随机推荐

  1. 中文字体@font-face的导入

    由于英文字母只有26个,所以生成.eot..woff..ttf..svg等文件是比较小的,也就十几KB而已.但是对于汉字来说,常用的汉字就已经2500个了,生成的文件一般要2-3MB,如此庞大的包对页 ...

  2. 【leetcode】867 - Transpose Matrix

    [题干描述] Given a matrix A, return the transpose of A. The transpose of a matrix is the matrix flipped ...

  3. 复习宝典之Mysql数据库

    查看更多宝典,请点击<金三银四,你的专属面试宝典> 第一章:mysql数据库 1)mysql与mariaDb MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用 ...

  4. Ubuntu如何挂载U盘

    1. 以root用户登陆 2. 查看当前挂载 fdisk -l 一般情况未挂载的硬盘都在最后,这里是/dev/sdb1 3.新建一个目录来挂载硬盘 挂载到MNT/usb root@h-Default- ...

  5. 如何用GDI+画个验证码

    如何使用GDI+来制作一个随机的验证码 绘制验证码之前先要引用 using System.Drawing; using System.Drawing.Drawing2D; 首先,先写一个方法来取得验证 ...

  6. Bootstrap01

    Bootstrap01内容概要 一.使用Bootstrap的步骤 1.下载Bootstrap类库,包含三个部分,fonts,css,Bootstrap 2.导入项目中,在头部引入JQ,css和Boot ...

  7. 一图看懂hadoop Yarn工作原理

    Hadoop 资源调度框架Yarn运行流程

  8. 执行Go程序的三种方式及Go语言关键字

    执行 Go 程序的三种方式及 Go 语言关键字 执行 Go 程序的三种方式 一.使用 go run 命令 二.使用 go build 命令 Step1. 对 go 源码源文件执行 go build 命 ...

  9. 《Java核心技术36讲》阅读笔记:谈谈对Java平台的理解笔记

    1. 谈谈你对Java平台的理解. Java是一种面向对象的语言,最显著的特性有两个方面: 一个就是一次编译,到处运行(Write once, run anywhere),能够非常容易的获得跨平台能力 ...

  10. Angular5学习笔记 路由配置

    因为angular-cli脚手架的关系,所以配置路由可以通过命令行来创建路由文件 原本创建一个angular项目的命令是ng new 项目名,就可以了,但这样创建出来的项目是没有路由文件的. 如果需要 ...