算法笔记(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. Struts2框架学习笔记--strtus2初识

    struts2概述: 1.struts2框架应用于javaEE三层结构中的Web层框架 2.struts2框架是在struts1和webwork基础之上发展的全新框架(脱胎换骨 ,用法完全不一样)ps ...

  2. Java中的监听器

    servlet的技术规范包括三个:servlet,listener,filter,今天记录一下listener的学习. 监听器就是监听某个对象的状态变化的技术.监听器包括事件源,监听器,注册监听器以及 ...

  3. II、Python HelloWorld

    大家都不是小孩子了,直接上 IDE 现在有个大问题!!没有解析器啊 这样 解析器地址比他多个 e OJBK

  4. 处理Model

    将Model对象归档解档 - CSDN博客 iOS archive(归档)的总结 - 苹果吧 - 博客园 IOS数据持久化之归档NSKeyedArchiver,iosnskeyedarchiver_I ...

  5. 一个input输入内容监听联动的demo

    两个input,一个在其中一个输入,内容在另一个input中实时回显 代码如下 <!DOCTYPE html> <html> <head> <title> ...

  6. Java常用修饰符总结

    修饰符是用于限定类型以及类型成员申明的一种符号,可用于修饰类.变量和方法,分为访问修饰符和非访问修饰符.访问修饰符控制访问权限,不同的访问修饰符有不同的权限范围,而非访问修饰符则是提供一些特有功能. ...

  7. 在TextBrowser显示中,如何让最新的数据永远出现在第一行或者是在窗口的最后显示信息

    这是第一行,但是随着数据的增多,最新的数据就会在末尾显示,然后就看不到了.可以用 main_ui->ReceiveDatatextBrowser->insertPlainText(strD ...

  8. 关于osi的7层与tcp的4层网络协议的理解

    osi 七层模型 应用层 提供接口 表示层 机器语言的二进制转换 对话层 决定是否传输 传输层 确定可不可靠 排差错 控流 网络层 提供逻辑地址 选路 数据链路层 mac 错误检测 物理层 设备间的比 ...

  9. Python 1.3 元组与文件

    一 Python元组Tuple类型 元组T= (1, 2, 3, 4)是不可变类型,属于序列,但顶层元素不可变,仅支持count()和index()操作. -*- coding:UTF- -*- # ...

  10. 加法变乘法——第六届蓝桥杯C语言B组(省赛)第六题

    原创 加法变乘法 我们都知道:1+2+3+ ... + 49 = 1225现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015 比如:1+2+3+...+10*11+12+...+27*28+ ...