代码随想录算法训练营Day41|背包问题、分割等和子集

智能车竞赛新手必看:用AD21从零画一块英飞凌TC264核心板(附开源PCB文件) 本文详细介绍了使用Altium Designer 21(AD21)从零开始设计英飞凌TC264核心板的完整流程,涵盖原理图绘制、PCB布线到最终DRC检查的全过程。针对智能车竞赛新手,提供了实用的硬件设计技巧和开源PCB文件,帮助快速掌握TC264核心板开发。 阅读详情

背包问题

二维

46. 携带研究材料(第六期模拟笔试) (kamacoder.com)

dp数组有两维,横轴表示背包重量j(0-j),纵轴表示不同物品(0-i),dp[i][j]即表示从下标为[0-i]的物品里任意取,对于重量为j的背包,最大的价值是多少。dp[i][j]的对物品i来说只有2种情况,物品i未放入或者放入,如果物品i未放入,由dp[i-1][j]可以推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i-1][j](当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)(参考代码随想录 (programmercarl.com))放物品时,

dp[i][j] =dp[i-1][j-weight[i]]+value[i],即当未放入i时,且重量为j-weight[i]的dp值加上i的价值。

即dp[i][j]的最终推导公式为:dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])

考虑到dp[i][j]的含义,则dp[i][0]意味着背包重量为0的价值,理应全为0,dp[i][0]的值初始化全部为0,此外当i为0时,若j<weight[0]时,dp[i][j]的值应该为0,因为背包容量比编号为0的物品重量要小,而当j>=weight[0]时,dp[0][j]的值应该是value[0],因为背包容量足够放编号为0的物品(注意这里是0-1背包问题,只有放入和取出两种操作,所以这里dp[0][j]只为values[0]而不是values[0]的倍数)

由于dp的递推公式dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]),当前dp[i][j]仅与之前的元素有关,其他地方无需初始化。

vector<vector<int>>dp(weight.size(),vector<int>(bagweight + 1, 0));
for(int j = weight[0]; j <= bagweight; j++){
    dp[0][j] = value[0];
}

之后是确定遍历顺序,对物品和背包的遍历都是可行的。

以遍历物品为例,当j<weight[i]时,无法将物品i放入,则dp[i][j] = dp[i-1][j],否则为上述的dp公式。

for(int i = 1; i < weight.size();i++){
    for(int j = 0; j <= bagweight; j ++){
        if(j < weight[i])
           dp[i][j] = dp[i-1][j];
        else
            dp[i][j] = max(dp[i][j-1],dp[i-1][j-weight[i]]+value[i]);
    }
}

遍历背包的话

for(int j = 0; j <= bagweight; j++){
    for(int i = 0; i < weight.size(); i++){
        if(j < weight[i])
            dp[i][j] = dp[i-1][j];
        else
            dp[i][j] = max(dp[i-1][j],dp[i-1][j-value[i]] + value[i]);
    }
}

只是变更一下顺序,其他一样(对本题是这样的)。

之后就是返回dp数组的最大值即可。

代码随想录的代码如下:

//二维dp数组实现
#include <bits/stdc++.h>
using namespace std;

int n, bagweight;// bagweight代表行李箱空间
void solve() {
    vector<int> weight(n, 0); // 存储每件物品所占空间
    vector<int> value(n, 0);  // 存储每件物品价值
    for(int i = 0; i < n; ++i) {
        cin >> weight[i];
    }
    for(int j = 0; j < n; ++j) {
        cin >> value[j];
    }
    // dp数组, dp[i][j]代表行李箱空间为j的情况下,从下标为[0, i]的物品里面任意取,能达到的最大价值
    vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));

    // 初始化, 因为需要用到dp[i - 1]的值
    // j < weight[0]已在上方被初始化为0
    // j >= weight[0]的值就初始化为value[0]
    for (int j = weight[0]; j <= bagweight; j++) {
        dp[0][j] = value[0];
    }

    for(int i = 1; i < weight.size(); i++) { // 遍历科研物品
        for(int j = 0; j <= bagweight; j++) { // 遍历行李箱容量
            // 如果装不下这个物品,那么就继承dp[i - 1][j]的值
            if (j < weight[i]) dp[i][j] = dp[i - 1][j];
            // 如果能装下,就将值更新为 不装这个物品的最大值 和 装这个物品的最大值 中的 最大值
            // 装这个物品的最大值由容量为j - weight[i]的包任意放入序号为[0, i - 1]的最大值 + 该物品的价值构成
            else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
        }
    }
    cout << dp[weight.size() - 1][bagweight] << endl;
}

int main() {
    while(cin >> n >> bagweight) {
        solve();
    }
    return 0;

算法使用两层嵌套循环来补全dp数组,外层执行weight.size()次,即n次,内层执行了bagweight+1次,定为m次,时间复杂度为O(n*m),空间复杂度使用了二维数组,O(n*m)。

一维

滚动数组,不太理解,周末看看。

代码随想录 (programmercarl.com)

// 一维dp数组实现
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 读取 M 和 N
    int M, N;
    cin >> M >> N;

    vector<int> costs(M);
    vector<int> values(M);

    for (int i = 0; i < M; i++) {
        cin >> costs[i];
    }
    for (int j = 0; j < M; j++) {
        cin >> values[j];
    }

    // 创建一个动态规划数组dp,初始值为0
    vector<int> dp(N + 1, 0);

    // 外层循环遍历每个类型的研究材料
    for (int i = 0; i < M; ++i) {
        // 内层循环从 N 空间逐渐减少到当前研究材料所占空间
        for (int j = N; j >= costs[i]; --j) {
            // 考虑当前研究材料选择和不选择的情况,选择最大值
            dp[j] = max(dp[j], dp[j - costs[i]] + values[i]);
        }
    }

    // 输出dp[N],即在给定 N 行李空间可以携带的研究材料最大价值
    cout << dp[N] << endl;

    return 0;
}

分割等和子集

416. 分割等和子集 - 力扣(LeetCode)

        本来想着直接排序然后依次加入最小的数,然后发现果然有错[1,1,2,2]。

        以[1,5,11,5]这个题例为例,可以抽象为 一个背包容量为11,剩余元素(只能使用1次)是否能装满这个容量为11的背包。0-1背包问题。

        DP数组含义,容量为j的最大价值为dp[j],当dp[target] == target时,表示能装满(此处的target为数组sum的一半,因为两个子集和要相等),即能实现分割等和子集。

        背包容量从0到10001,因为数字总和不超过20000,则target<=10000,dp数组长度到达10001就够了。

        dp[j] = max(dp[j],dp[j - nums[i]]+ nums[i]);

        对dp的初始化,由于nums数组全为正整数,可以全部初始化为0,(若存在负数,则应初始化为INT_MIN)。

遍历顺序物品遍历在外,背包遍历在内层,且内层倒序遍历。参考代码随想录 (programmercarl.com)

最后需考虑,当dp[target] == target时,返回true,否则为false。

此外,若sum%2 == 1,则表明sum为奇数,不存在两个相等的子数组和,return false。剪枝。

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0; 
        for(auto x:nums){
            sum += x; // 计算数组元素的总和
        }
        // 如果总和是奇数,那么不能平分,直接返回false
        if(sum%2 == 1)
            return false;
        // 计算目标和,即每个子集应该达到的和
        const int target = sum/2;
        // 初始化动态规划数组dp,大小为10001,初值都为0
        // dp[j]表示是否能够从前i个数字中选取一些数字,使得这些数字的和为j
        vector<int>dp(10001, 0);

        // 遍历数组中的每个数字
        for(int i = 0; i < nums.size();i++){
            // 从大到小遍历目标和及其以下的值
            for(int j = target; j >= nums[i]; j--){
                // 更新dp[j],选取或不选取当前数字,取两种情况的最大值
                dp[j] = max(dp[j],dp[j - nums[i]] +nums[i]);
            }
        }
        // 如果dp[target]等于target,说明可以找到和为target的子集,返回true
        if(dp[target] == target)
            return true;
        return false;
    }
};

算法的时间复杂度为O(n^2),空间复杂度为O(n)。

【系统架构设计师】预测试卷四:综合知识(75道选择题) 本文整理系统架构设计师考试高频考点,涵盖计算机系统基础、计算机网络、数据库、软件工程与UML四大模块,共28道典型题目。重点解析Cache局部性原理、RISC/CISC区别、TCP三次握手、B+树索引优势、CAP定理、螺旋模型特点等核心概念,并标注易错选项,帮助考生快速掌握解题思路。 关键词:系统架构、Cache、RISC、TCP、B+树、CAP定理、螺旋模型 阅读详情

相关推荐

CentOS 7下rsyslog日志服务器搭建全攻略:从安装到避坑

本文详细介绍了在CentOS 7系统上搭建rsyslog日志服务器的完整流程,从基础安装到高级配置,包括协议设置、日志模板设计、安全加固和性能优化。特别分享了生产环境中的实战技巧和常见问题解决方案,帮助用户高效构建可靠的日志管理系统。

happy2的博客 687

代码随想录算法训练营Day 41 || 01 背包问题、滚动数组、416. 分割等和子集

01背包问题是一种典型的组合优化问题,它可以描述为:给定一组物品,每种物品都有自己的重量和价值,在限定的最大重量内,选择若干物品装入背包,使得包内物品的总价值最大。问题可以形式化为:假设有\( N \)件物品和一个容量为\( W \)的背包。第\( i \)件物品的重量是\( w_i \),其价值为\( v_i \)。求解将哪些物品装入背包可使这些物品的总价值最大,同时不超过背包的容量。

m0_66462858的博客 218

rk3576之imx415 4k@60fps

1;0;1;0;1;0;1;0;1;0;1;0;1;0;

darennet的专栏 704

代码随想录算法训练营day41 | 01背包问题 二维、01背包问题 一维、416. 分割等和子集

背包问题的理论基础重中之重是01背包。

sunflowers11的博客 560

嵌入式工程师成长之路(1)——元件基础(试读版)

上拉电阻阻值选错导致MCU反复重启?0欧电阻竟然能“背锅”信号干扰?高精密采样电阻的温漂毁了整个控制系统?——这些问题,都是基础不牢!优快云硬件领域头部博主十年经验汇总,涵盖电阻分类、封装、实战选型、避坑指南,附带职业进阶路径,助你从小白进阶为“电路医生”!

云轩阁 34万+

基于Jeecgboot3.9.0的flowable7.2.0流程增加一个OA请假单功能例子(二)

基于Jeecgboot3.9.0的flowable7.2.0流程增加一个OA请假单功能例子(二)

宁波阿成的博客 198

代码随想录算法训练营DAY41|背包问题 二维 、背包问题 一维、416. 分割等和子集

【代码】代码随想录算法训练营DAY41|背包问题 二维 、背包问题 一维、416. 分割等和子集。

Greeneril_的博客 401

华为OD机试真题 新系统 2026-07-22 Java&Go&C 实现【最小代价完成论文评审】

某校有 n 篇论文需要分配给教师评审。 每篇论文 i 可由 files[i] 对应的教师列表中任一教师评审。 每篇论文至少需要一名教师评审。 每位教师 t 不论被分配多少篇论文,其评审费用固定为 cost[t]。 请给出参与评审教师数量最少时的总费用。 如果存在多种方案满足教师数量最少,则选择总费用最小的方案。

MISAYAONE的博客 147

代码随想录-算法训练营day41【动态规划04:01背包问题-滚动数组、分割等和子集】

代码随想录-算法训练营day41【动态规划04:01背包问题-滚动数组、分割等和子集】

upward 560

基于MATLAB实现语音信号MFCC特征提取(附完整代码)

你有没有想过你的智能手机是如何理解语音指令的?或者 Alexa 和 Siri 等语音助手如何处理您的命令?这种卓越能力背后的机制在很大程度上归功于一种称为 Mel 频率倒谱系数 (MFCC) 的方法。语音识别技术允许机器解释人类语音,将口语转换为计算机可以操纵的格式。这项技术对于开发交互式和响应式 AI 至关重要,例如声控助手、自动化客户服务系统和实时翻译服务。MFCC 代表 Mel 频率倒谱系数。这是用于自动语音和说话人识别的功能。

baidu_34971492的博客 1313

游戏开发中的CV:实时动作捕捉与虚拟交互

游戏开发中的CV:实时动作捕捉与虚拟交互​ ,人工智能,计算机视觉,大模型,AI,在当今游戏产业中,玩家对游戏体验的要求日益提高,追求更加真实、沉浸的交互感受。计算机视觉(Computer Vision,CV)技术的飞速发展,为游戏开发带来了革命性的突破,其中实时动作捕捉与虚拟交互技术更是成为提升游戏品质的核心驱动力。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 16万+

代码随想录算法训练营第23期day41|01背包问题、01背包问题——滚动数组、416. 分割等和子集

在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。

weixin_42179093的博客 199

人工智能训练师(三级)操作技能考核·自测卷

为您定制了一份。这份试卷严格拆分了“业务分析”、“智能训练”、“智能系统设计”、“培训与指导”四大模块,所有填空题均来源于上一轮整理的。您可以先用它进行“第二步(抛开答案自己填)”,填完后对照末尾的答案速查进行“第一步(补全并运行)”的校验,最后标记错题进行“第三步(针对性重复练习)”。

suny8088的博客 102

代码随想录算法训练营Day41 | 背包问题 一维、背包问题 二维、LeetCode416. 分割等和子集

背包问题:用若干件物品装入固定容量的背包,使得背包内物品价值最大,我们有若干件物品体积的数组,也有物品价值的数组。01背包问题:每件物品只有一个。在解决背包问题时,明确递归五部曲:1、dp[i][j]数组含义:从[0,i]个物品放在容量为j的背包中获得的最大价值。2、递推公式:分两种情况(1)没有放物品i:dp[i][j]=dp[i-1][j];(2)放了物品i:dp[i][j]=dp[i-1][j-weight[i]]。(这个思路很难想)那么递推公式就是取其中的最大值。

ckw_lztxdy的博客 502

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

代码随想录算法训练营Day41 ||leetCode 0-1背包问题 || 416. 分割等和子集

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);将sum/2看作背包容量,每一个数看作重量,进行遍历。如果背包恰好能装满,说明存在一个子集和为sum/2。dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。二维数组简化为一维,注意背包从大到小遍历,避免重复放入第一个物品。那么可以有两个方向推出来dp[i][j],416. 分割等和子集。

qq_44884699的博客 635

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

代码随想录算法训练营Day41 | 01背包问题(二维)、01背包问题(一维)、416.分割等和子集 | Python | 个人记录向

动态规划:01背包问题(二维)、01背包问题(一维)、416.分割等和子集。

Python基本算法 581

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

代码随想录算法训练营Day41 | 01背包问题,你该了解这些! 01背包问题,你该了解这些! 滚动数组 416. 分割等和子集

思路:用重量和数量依次遍历 i为个数, j为容量int。

qq_24817679的博客 296

代码随想录-算法训练营day41(动态规划04:01背包,01背包滚动数组,分割等和子集)

动态规划04:01背包原来是这样啊!

weixin_61931006的博客 861

Day41 算法训练营

第一行dp[0]【j】初始化时,只有背包容量为物品0容量的时候,方法为1,表示正好装满,其他情况下,要么装不满,要么装不下,所以dp[0]【nums[0]】=1,其余均为0。第一列dp[i]【0】中都是只有1种方法,即放0件物品i,但存在物品0的重量为0的情况,故存在几个重量为0的物品,就应将指定的dp数组元素值置为2的几次方。递推公式:dp[i]【j】=dp[i - 1]【j】+dp[i - 1]【j - nums[i]】:即背包容量为j,里面不放物品i,装满有dp[i - 1]【j】中方法。

qq_54162207的博客 546

代码随想录算法训练营第day41|背包理论基础、416. 分割等和子集

dp[i][j]由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值。dp[i][j]由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j];当容量为j,物品编号为0时,

qq_60513199的博客 1205

【代码随想录算法训练营Day40】01背包问题一维dp数组;二维dp数组(滚动数组);416.分割等和子集

如果做过背包类问题,可以先看视频,很多内容,是自己平时没有考虑到位的。背包问题,力扣上没有原题,大家先了解理论,今天就安排一道具体题目。正式开始背包问题,背包问题还是挺难的,虽然大家可能看了很多背包问题模板代码,感觉挺简单,但基本理解的都不够深入。如果是直接从来没听过背包问题,可以先看文字讲解慢慢了解 这是干什么的。物品要从第二个开始,也就是i要从1开始。利用回溯列举出每一种方法。

Tammy2001的博客 1248

代码随想录算法训练营day41

初始化,只初始化一行,dp[0]肯定为0,其他下标位置,也初始化为0,因为后面递推过程中会逐渐取最大值;然后第二步递推公式,要递推考虑第i个物品,有两种情况,首先是不放i物品,这时候dp[i][j]=dp[i-1][j],与前i-1个物品的结果相同,然后是放i物品,这时候背包还剩下的重量为j-weight[i],然后在这些重量中放置前i-1个物品,dp[i][j]=dp[i-1][j-weight[i]]+value[i],最终递推即在这两个里取最大值,如果物品i本来就放不进去,那么就只有第一种情况;

weixin_43390031的博客 1210

代码随想录算法训练营day41|第九章 动态规划part04

01背包问题 二维01背包问题 二维。

mrmobi的博客 1210

【代码随想录】【算法训练营】【第41天】 [416]分割等和子集

思路及算法思维,指路。题目来自。day 40,休息,休息一下~day 41,艰难的周一~

day day up 468

代码随想录算法训练营Day41 | 0-1背包理论基础、416.分割等和子集

一维数组,使用滚动数组来实现背包。方便理解使用二维数组来解释定义:dp[i][j]表示 n = i 时,数组下标[0, i]中取任意数所能得到的最大值,这个最大值不能超过j。

Y_Vollerei的博客 618

【LeetCode】416. 分割等和子集(中等)——代码随想录算法训练营Day41

【LeetCode】416. 分割等和子集

晴雪月乔的博客 616
上一篇: 代码随想录算法训练营Day39|62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树
下一篇: 代码随想录算法训练营Day42|1049.最后一块石头的重量II、494.目标和、474.一和零
viaNoir
博客等级 码龄10年 535粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值