[Algorithm][动态规划][01背包问题][模板 背包][分割等和子集]详细讲解 +何为背包问题?

目录

  • 0.何为背包问题?
  • 1.模板 背包
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.分割等和子集
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


0.何为背包问题?

  • 背包问题:有限制条件下的"组合问题"

  • 你有一个背包,地上有一堆物品,挑选一些物品放入背包中

    • 问:最大能挑选出来的价值是多少?
  • 限制因素

    • 物品的属性:价值等
    • 背包的属性:容量大小等
    • 背包是要求必装满还是不必装满?
      请添加图片描述
  • 当研究一个问题,出现选或者不选的情况,思路就可以往01背包上靠

  • 注意:背包问题是必须要掌握的算法问题


1.模板 背包

1.题目链接

  • [模板] 背包

2.算法原理详解

  • 注意:01背包问题是所有背包问题的基础,此处的分析思路,可以用到很多题里面
  • 思路
    • 确定状态表示 -> dp[i][j]的含义

      • dp[i]:从前i个物品中选,所有选法中,能挑选出来的最大价值 ×
        • 无法得知背包容量
      • 不要求恰好装满
        • dp[i][j]:从前i个物品中挑选,总体积不超过j,所有选法中,能挑选出来的最大价值
      • 要求恰好装满
        • dp[i][j]:从前i个物品中挑选,总体积恰好等于j,所有选法中,能挑选出来的最大价值
    • 推导状态转移方程:根据最后一个位置的情况,分情况讨论

      • 不要求恰好装满:j - v[i] >= 0是为了确保背包此时容量足够塞下当前物品
        请添加图片描述

      • 要求恰好装满dp[i][j] == -1表示没有这种情况,即此时总体积凑不到j
        请添加图片描述

    • 初始化:

      • 不要求恰好装满vector<vector<int>> dp(n + 1, vector<int>(V + 1))
      • 要求恰好装满:第一行除第一个位置,其余都为-1
    • 确定填表顺序:从上往下

    • 确定返回值:

      • 不要求恰好装满dp[n][V]
      • 要求恰好装满dp[n][V] == -1 ? 0 : dp[n][V]
  • 滚动数组优化空间
    • 每次填值,只依赖上一行的值

      • 所以,理论上只需要两行一维数组,就可以解决问题
    • 可以一个一维数组就优化掉此问题

      • 但是如果从左往右遍历数组,会影响动态规划填值
        • 因为原本的填值过程,会依赖左上方的值
      • 此时,只需要从右往左遍历该数组,就不会影响动态规划的规程
        请添加图片描述

      请添加图片描述

    • 操作

      • 删除所有的横坐标
      • 修改一下j的遍历顺序
    • 注意不要去强行解释优化后的妆台表示以及状态转移方程,费时费力还没啥意义


3.代码实现

// v1.0
int main()
{
    int n = 0, V = 0;
    cin >> n >> V;
    
    vector<int> v(n + 1), w(n + 1);
    for(int i = 1; i <= n; i++)
    {
        cin >> v[i] >> w[i];
    }
    
    vector<vector<int>> dp(n + 1, vector<int>(V + 1));
    
    // Q1
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= V; j++)
        {
            dp[i][j] = dp[i - 1][j];
            if(j >= v[i])
            {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
            }
        }
    }
    cout << dp[n][V] << endl;

    // Q2
    dp.resize(n + 1, vector<int>(V + 1));
    for(int i = 1; i <= V; i++)
    {
        dp[0][i] = -1;
    }

    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= V; j++)
        {
            dp[i][j] = dp[i - 1][j];
            if(j >= v[i] && dp[i - 1][j - v[i]] != -1)
            {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
            }
        }
    }
    cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << endl;

    return 0;
}
-----------------------------------------------------------------------------
// v2.0 滚动数组优化
int main()
{
    int n = 0, V = 0;
    cin >> n >> V;
    
    vector<int> v(n + 1), w(n + 1);
    for(int i = 1; i <= n; i++)
    {
        cin >> v[i] >> w[i];
    }
    
    vector<int> dp(V + 1);
    
    // Q1
    for(int i = 1; i <= n; i++)
    {
        for(int j = V; j >= v[i]; j--)
        {
            dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
        }
    }
    cout << dp[V] << endl;

    // Q2
    dp.resize(V + 1, 0);
    for(int i = 1; i <= V; i++)
    {
        dp[i] = -1;
    }

    for(int i = 1; i <= n; i++)
    {
        for(int j = V; j >= v[i]; j--)
        {
            if(dp[j - v[i]] != -1)
            {
                dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
            }
        }
    }
    cout << (dp[V] == -1 ? 0 : dp[V]) << endl;

    return 0;
}

2.分割等和子集

1.题目链接

  • 分割等和子集

2.算法原理详解

  • 问题转化:在数组中选择一些数出来,让这些数的和等于sum / 2 --> 01背包
  • 思路
    • 确定状态表示 -> dp[i][j]的含义

      • dp[i]j]:从前i个数中****,所有的选法中,能否凑成j这个数
    • 推导状态转移方程:根据最后一个位置的情况,分情况讨论

      • dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]
        请添加图片描述
    • 初始化:

      • 多开一行及一列虚拟结点
        请添加图片描述
    • 确定填表顺序:从上往下

    • 确定返回值:dp[n][sum / 2]

  • 滚动数字优化同[模板] 背包

3.代码实现

// v1.0
bool canPartition(vector<int>& nums) 
{
    int n = nums.size(), sum = 0;
    for(auto& x : nums)
    {
        sum += x;
    }

    if(sum % 2) return false;

    int aim = sum / 2;
    vector<vector<bool>> dp(n + 1, vector<bool>(aim + 1));

    // Init
    for(int i = 1; i <= n; i++)
    {
        dp[i][0] = true;
    }

    // DP
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= aim; j++)
        {
            dp[i][j] = dp[i - 1][j];
            if(j >= nums[i - 1])
            {
                dp[i][j] = dp[i][j] || dp[i - 1][j - nums[i - 1]];
            }
        }
    }

    return dp[n][aim];
}
----------------------------------------------------------------------
// v2.0 滚动数组优化
bool canPartition(vector<int>& nums) 
{
    int n = nums.size(), sum = 0;
    for(auto& x : nums)
    {
        sum += x;
    }

    if(sum % 2) return false;

    int aim = sum / 2;
    vector<bool> dp(aim + 1);                
    dp[0] = true;

    // DP
    for(int i = 1; i <= n; i++)
    {
        for(int j = aim; j >= nums[i - 1]; j--)
        {
            dp[j] = dp[j] || dp[j - nums[i - 1]];
        }
    }

    return dp[aim];
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

递归(全排列andN皇后)

全排列 分治与递归 递归是实现分治的一种方法 思想思路 题目&#xff1a; 全排列i 我这样直接输出会多输出一个空行&#xff08;最后一个\n&#xff09; #include<stdio.h>using namespace std; const int maxn10; int an[maxn]; int n; bool hash[maxn]{0}; int c0…

IP SSL使用率增长有利于网络安全防护!

目录 IP的特殊性 IP证书的作用原理&#xff1a; 申请IP证书的基本条件&#xff1a; 申请IP SSL证书&#xff1a; 对于SSL证书来说&#xff0c;很多朋友应该并不陌生&#xff0c;目前SSL证书广泛应用在域名服务器上&#xff0c;所以大家最熟悉的证书类型可能就是单域名SSL证…

MeiliSearch-轻量级且美丽的搜索引擎

MeiliSearch-轻量级且美丽的搜索引擎 MeiliSearch 是一个功能强大、快速、开源、易于使用和部署的搜索引擎。它具有以下特点&#xff1a; 支持中文搜索&#xff1a;MeiliSearch 对中文有良好的支持&#xff0c;不需要额外的配置。高度可定制&#xff1a;搜索和索引都可以高度…

UE4获取动画序列资产的动画时长

谢谢”朝闻道“大佬的指点~

数据脱敏技术方案选择(word)

1 概述 1.1 数据脱敏定义 1.2 数据脱敏原则 1.2.1基本原则 1.2.2技术原则 1.2.3管理原则 1.3 数据脱敏常用方法 3.1.1泛化技术 3.1.2抑制技术 3.1.3扰乱技术 3.1.4有损技术 1.4 数据脱敏全生命周期 2 制定数据脱敏规程 3 发现敏感数据 4 定义脱敏规则 5 执…

SpringCache和SpringTask

SpringCache 在启动类上加EnableCaching注解 我们只要在Controller上写一个SpringCache相应的注解 我们就能实现缓存了 简化缓存操作代码&#xff0c;提高我们的效率 我们默认是我们的spring做缓存 但我们还可以替换我们的缓存技术 例如 EhCache Google Redis 来作为…

three.js指南

threejs 相关资料 threejs 官网threejs 案例 安装&#xff08;Installation&#xff09; 使用 NPM 和构建工具进行安装 对于大多数用户而已&#xff0c;从 npm 包注册表中心 安装并使用 构建工具 会是一个更推荐的方案。因为项目需要的依赖越多&#xff0c;就越有可能遇到静…

1.vue2.x-初识及环境搭建

目录 1.下载nodejs v16.x 2.设置淘宝镜像源 3.安装脚手架 4.创建一个项目 5.项目修改 代码地址&#xff1a;source-code: 源码笔记 1.下载nodejs v16.x 下载地址&#xff1a;Node.js — Download Node.js 2.设置淘宝镜像源 npm config set registry https://registry.…

【PyTorch】PyTorch深度学习框架实战(二):torchrun

一、引言 PyTorch由facebook人工智能研究院研发&#xff0c;2017年1月被提出&#xff0c;是一个开源的Python机器学习库&#xff0c;基于Torch&#xff0c;用于自然语言处理等应用程序。PyTorch既可以看作加入了GPU支持的numpy&#xff0c;同时也可以看成一个拥有自动求导功能的…

【iOS】MRC下的单例模式批量创建单例

单例模式的介绍和ARC下的单例请见这篇&#xff1a;【iOS】单例模式 目录 关闭ARC环境MRC下的单例ARC下的单例批量创建单例Demo 关闭ARC环境 首先关闭ARC环境&#xff0c;即打开MRC&#xff1a; 或是指定某特定目标文件为非ARC环境&#xff1a; 双击某个类文件&#xff0c;指定…

python的最小二乘法(OLS)函数

1、作用 pandas提供了一些很方便的功能&#xff0c;比如最小二乘法(OLS)&#xff0c;可以用来计算回归方程式的各个参数。 2、Python导出的OLS模型的结果 下面是如何解读Python导出的OLS模型的结果。 1. 回归系数&#xff1a; 代表每个自变量对因变量的影响程度&#xff0c…

软件质量保障与测试 Lab2

Lab2 12修改代码执行结果问题解决 3修改代码执行结果问题解决 1 klee 对 symbolic.c 生成文件的执行结果&#xff1a; 2 修改代码 头文件引用添加&#xff1a; #include <klee/klee.h>执行部分&#xff1a; 将原先的读入&#xff1a; int main() {maze[y][x] X;re…

Wakeup Source框架设计与实现

Wakeup Source 为系统组件提供了投票机制&#xff0c;以便低功耗子系统判断当前是否可以进入休眠。 Wakeup Source(后简称&#xff1a;WS) 模块可与内核中的其他模块或者上层服务交互&#xff0c;并最终体现在对睡眠锁的控制上。 1. 模块功能说明 WS的处理逻辑基本上是围绕 com…

Python初步使用教程

1.基本输出print函数 a10 b20 print(a)#输出结束后会自动换行 print(b) print(a,b,猪猪侠)#print中sep决定三者之间会存在空格#连接方法一 print(猪猪,end) print(侠) #连接方法二&#xff08;只能是字符串和字符串连&#xff09; print(超级无敌)print(chr(67)) print(ord(猪…

内存经验分享

目录 内存统计工具 /proc/meminfo Buddy ​​​​​​​​​​​​​​Slub ​​​​​​​Procrank /proc/pid/smaps ​​​​​​​Dumpsys meminfo 内存评估 内存泄漏 Lmk 水位调整 内存统计工具 /proc/meminfo 可以提供整体内存信息&#xff0c;各字段表示的意思如…

Ant Design Pro

一&#xff1a;Ant Design pro是什么&#xff1a; Ant Design Pro 是基于 Ant Design 和 umi 的封装的一整套企业级中后台前端/设计解决方案&#xff0c;致力于在设计规范和基础组件的基础上&#xff0c;继续向上构建&#xff0c;提炼出典型模板/业务组件/配套设计资源&#x…

[linux] 上手新ubuntu机器的初始化工作(自用侵删)

文章目录 环境类Vimzshother 应用类Typora激活环境准备解包替换文件app.asar激活Typora VsCodeextension.vscode乱码 WattToolkitQQWPS输入法:FcitxDeepin-wine : Wechat 环境类 Vim 直接贴配置 vim-Plug: let mapleader "," let g:mapleader "," le…

攻防世界---misc---小小的PDF

1、题目描述&#xff0c;下载附件是一个PDF&#xff0c;打开之后是这样&#xff0c;有两页PDF 2、用winhex分析&#xff0c;没有发现奇怪的地方 3、在kali中binwalk发现有多张照片 4、接着使用foremost将图片分离出来&#xff0c; 5、得到3张图片&#xff0c;打开第3张图片&am…

【TB作品】MSP430F5529 单片机,智能温控系统,DS18B20

作品功能 本项目设计并实现了一个基于MSP430单片机的智能温控系统。系统可以实时显示当前温度&#xff0c;并且可以根据设置的临界值对环境进行加热或降温。主要功能如下&#xff1a; 实时显示当前温度。显示并调整温度临界值&#xff0c;临界值可在20~35摄氏度之间调节。当前…

STM32-呼吸灯仿真

目录 前言: 一.呼吸灯 二.跑马灯 三. 总结 前言: 本篇的主要内容是关于STM32-呼吸灯的仿真,包括呼吸灯,跑马灯的实现与完整代码,欢迎大家的点赞,评论和关注. 接上http://t.csdnimg.cn/mvWR4 既然已经点亮了一盏灯,接下来就可以做更多实验了, 一.呼吸灯 在上一个的基础上…