Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >你的背包,让我走的好缓慢

你的背包,让我走的好缓慢

作者头像
opencode
发布于 2022-12-26 08:02:35
发布于 2022-12-26 08:02:35
31100
代码可运行
举报
文章被收录于专栏:知识同步知识同步
运行总次数:0
代码可运行

动态规划,01背包问题

背包问题是经典的动态规划问题,这里先说一下简单的01背包

问题是这样的:

一共有N件物品,第i(i从1开始)件物品的重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?

最简单的思路就是,枚举所有情况,每个物品都有放或者不放两种情况,那N个物品,就是2^N种情况,数量级直接爆炸。

动态规划的思想就是能不能利用子问题的解,来求解当前问题

现在有个实例,物品个数n=3,背包容量w=5,重量数组weights={2,4,1}, 价值数组values={10,5,4}

假设dp[n][w]表示前N个物体装入w容量的背包能装入的最大价值,构成一个二维表,dp的过程就是填表的过程

构建一个二维表来填空,其中列表示容量,行表示第i个物品,所以对应的重量和价值数组需要对应下标为i-1

对于边界条件,第0个物品,也就是没有物品可放时,有再多的容量也没用,所以对应的价值都为0

同样的,当容量为0时,有再多的物品也没用,对应的价值都为0

那从dp[1][1]开始填表,

第一个物品,如果他的重量大于当前容量,就不考虑放进去,所以和上一个物品判断的结果一样,则dp[i][j]=dp[i-1][j]

如果他的重量小于等于当前容量,可以考虑放进去或者不放进去,就出现了两种情况,需要选取两种情况的最大值,若不放进去就是dp[i][j]=dp[i-1][j],如果放进去,当前容量为j-weights[i-1],再加上当前物品的价值values[i-1],即dp[i][j]=max(dp[i-1][j], dp[i-1][j-weights[i-1]]+values[i-1])

在这里,物品重量是大于当前容量的,所以遵循dp[i][j]=dp[i-1][j],找到dp[0][1]

这里也是一样的

到这里,物品重量等于容量的,所以需要找到dp[i-1][j]dp[i-1][j-weights[i-1]]+values[i-1]两个数值进行对比,在这里就是dp[2][1]和dp[2][0]+4,

其他的元素以此类推,填满整个二维表

至此,dp[n][w]即为最大价值。

代码为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n=3;
    int w = 5;
    vector<int> weights = { 2,4,1 };
    vector<int> values = { 10,5,4 };
    vector<vector<int>> dp(n+1, vector<int>(w+1,0));

    for (int i = 0; i < n+1; i++) dp[i][0] = 0;
    for (int j = 0; j < w+1; j++) dp[0][j] = 0;

    for (int i = 1; i < n+1; i++) {
        for (int j = 1; j < w + 1; j++) {
            if (j > weights[i - 1]) {
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);
            }
            else dp[i][j] = dp[i - 1][j];
        }
    }

    for (int i = 0; i < n + 1; i++) {
        for (int j = 0; j < w + 1; j++) {
            cout << dp[i][j] << " ";
        }
        cout << endl;
    }

    cout << dp[n][w];
}

到这里二维的dp过程就结束了,其实我们观察一下,会发现,对于每一列,其实我们只关心每一个书包容量下能装下的最大价值,所以我们只需要保存每一列的最大值即可,所以将二维的dp转为一维的dp

dp方程也改为dp[j]=max(dp[j],dp[j-weights[i-1]]+values[i-1])

代码为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main() {
    int n = 3;
    int w = 5;
    vector<int> weights = { 2,4,1 };
    vector<int> values = { 10,5,4 };
    vector<int> dp(w + 1, 0);

    for (int i = 1; i < n + 1; i++) {
        for (int j = w; j > 1; j--) {
            if (j >= weights[i - 1]) {
                dp[j] = max(dp[j], dp[j - weights[i - 1]] + values[i - 1]);
            }
        }
    }

    for (int j = 0; j < w + 1; j++) {
        cout << dp[j] << " ";
    }

    cout <<endl<< dp[w];
}

这里要注意下j遍历的顺序,这个挺重要的

好的,今天就到这里了,下一次会介绍01背包引申出来的题目

参考链接 https://zhuanlan.zhihu.com/p/93857890

https://www.nowcoder.com/questionTerminal/2820ea076d144b30806e72de5e5d4bbf

https://www.nowcoder.com/questionTerminal/fd55637d3f24484e96dad9e992d3f62e?answerType=1&f=discussion

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
01背包及其变种(物品无限背包、恰好装满背包)
一、01背包问题   01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解将那些物品装入背包可使总价值最大。   动态
用户1215536
2018/02/05
4.6K0
01背包及其变种(物品无限背包、恰好装满背包)
最详细动态规划解析——背包问题
要解决一个复杂的问题,可以考虑先解决其子问题。这便是典型的递归思想,比如最著名的斐波那契数列,讲递归必举的例子。
全栈程序员站长
2022/09/19
3640
最详细动态规划解析——背包问题
文心一言 VS 讯飞星火 VS chatgpt (215)-- 算法导论16.2 2题
0-1 背包问题是一个典型的动态规划问题,其目标是在给定的重量限制下最大化背包中物品的总价值。每个物品可以选择放入背包或不放入背包(0-1表示),并且每种物品只有一个。
福大大架构师每日一题
2024/03/18
1130
文心一言 VS 讯飞星火 VS chatgpt (215)-- 算法导论16.2 2题
01背包精讲
给定一个物品集合s={1,2,.....,n},物品i具有重量wi和价值vi。背包能承受能承受的最大载重量不超过W。背包问题就是找到一个物品子集s‘属于s,使得maxEwi<=W。所谓01背包就是物品要么整个地选取,要么不取。 首先我们先要肯定一件事,假设子问题(i,w)的最优装载中含有物品i,则其中的子问题(i-1,w-wi)的装载方案也一定是最优的。 证明:(反证法)假设子问题(i-1,w-wi)的装载方案p不是最优的,则有一个更优的装载方案p',将p'替换p然后在加上物品i将会比原来
用户1624346
2018/04/11
7350
算法修炼之筑基篇——筑基一层初期(解决01背包问题)
在C/C++中,可以使用动态规划来解决01背包问题。动态规划是一种常用的解决优化问题的算法思想,它通过将问题分解为子问题,并利用子问题的解来构建更大规模的问题的解。
命运之光
2024/03/20
1180
算法修炼之筑基篇——筑基一层初期(解决01背包问题)
把01背包问题的底裤扒个底朝天!!!
有N件物品和一个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
大忽悠爱学习
2021/11/15
3470
0-1背包问题分析
对于j=1,wj=2,pj=2,Y=1时,有wj > Y,因此放不下,所以沿用前(j-1)个时的价值,而Y不变。
小锋学长生活大爆炸
2021/09/10
3960
0-1背包问题分析
动态规划:关于01背包问题,你该了解这些!
背包问题的经典资料当然是:背包九讲。在公众号「代码随想录」后台回复:背包九讲,就可以获得背包九讲的PDF。
代码随想录
2021/01/28
2.6K0
背包九讲—-整理+例题[通俗易懂]
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。
全栈程序员站长
2022/08/03
1.1K0
背包九讲—-整理+例题[通俗易懂]
01背包精讲
给定一个物品集合s={1,2,…..,n},物品i具有重量wi和价值vi。背包能承受能承受的最大载重量不超过W。背包问题就是找到一个物品子集s‘属于s,使得maxEwi<=W。所谓01背包就是物品要么整个地选取,要么不取。 首先我们先要肯定一件事,假设子问题(i,w)的最优装载中含有物品i,则其中的子问题(i-1,w-wi)的装载方案也一定是最优的。 证明:(反证法)假设子问题(i-1,w-wi)的装载方案p不是最优的,则有一个更优的装载方案p’,将p’替换p然后在加上物品i将会比原来的最优装载价值最大,与
用户1624346
2018/04/17
8180
【从二维到一维:动态规划——01背包完全背包的空间优化之路】—— 经典例题解答,将问题转化为背包问题
二维DP 中,我们需要一个 n+1 行,W+1 列的数组,dp[i][w] 表示前 i 个物品能够填充容量为 w 的背包。
用户11286421
2025/03/11
2410
【从二维到一维:动态规划——01背包完全背包的空间优化之路】—— 经典例题解答,将问题转化为背包问题
文心一言 VS 讯飞星火 VS chatgpt (216)-- 算法导论16.2 3题
在0-1背包问题中,如果商品的重量递增序与价值递减序完全一样,那么我们可以利用这个特性设计一种高效的算法。对于这种情况,我们可以从重量最轻、价值最高的商品开始考虑,依次判断是否可以放入背包中。这种策略是基于一个直观的观察:更重的物品往往价值更低,所以我们应该优先考虑轻且价值高的物品。
福大大架构师每日一题
2024/03/18
1290
文心一言 VS 讯飞星火 VS chatgpt (216)-- 算法导论16.2 3题
动态规划:完全背包、多重背包[通俗易懂]
  完全背包:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。    
全栈程序员站长
2022/09/17
8650
动态规划:完全背包、多重背包[通俗易懂]
你的背包,被我找到了(0-1背包问题)
给你一个可装载重量为W的背包和N个物品,每个物品有重量和价值两个属性。其中第i个物品的重量为wt[i],价值为val[i],现在让你用这个背包装物品,最多能装的价值是多少?
五分钟学算法
2020/03/12
7440
背包九讲
01背包九讲里面最简单的一种了,但是也是最重要的一种,其他的几种基本上都可以用01背包的解题思路来去解决,接下来结合例题来解决一下吧;
某些人
2020/04/09
5370
【算法】动态规划(二)
上一篇,介绍了动态规划DP的概念,以及暴力递归和动态规划的关系。这一篇,将介绍几道经典的动态规划题
MapleYe
2020/03/28
4520
0-1背包问题之滚动数组!
今天我们就来说一说滚动数组,其实在前面的题目中我们已经用到过滚动数组了,就是把二维dp降为一维dp,一些录友当时还表示比较困惑。
代码随想录
2022/03/07
9810
0-1背包问题之滚动数组!
经典动态规划:0-1 背包问题
东哥带你手把手撕力扣~ 作者:labuladong 公众号:labuladong 若已授权白名单也必须保留以上来源信息
labuladong
2021/09/23
6260
Python 算法基础篇:背包问题的动态规划解法
背包问题是计算机科学中一个重要的组合优化问题,动态规划是解决该问题的高效算法技术。本篇博客将重点介绍背包问题的动态规划解法,包括状态定义、状态转移方程、边界条件和状态转移过程,并通过实例代码演示动态规划算法的实现,每行代码都配有详细的注释。
小蓝枣
2023/07/25
7540
【C++】算法集锦(9):背包问题
给你一个载重量为 W 的背包,以及一堆物品,这些物品都有属于自己的两个属性:价值var和质量wt,试问这个背包最多能装多少价值的物品。
看、未来
2021/09/18
7360
推荐阅读
相关推荐
01背包及其变种(物品无限背包、恰好装满背包)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验