[Algorithm][动态规划][01背包问题][目标和][最后一块石头的重量Ⅱ]详细讲解

目录

  • 1.目标和
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.最后一块石头的重量 II
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


1.目标和

1.题目链接

  • 目标和

2.算法原理详解

  • 问题转化:在数组中选择一些数,让这些数的和等于a,一共有多少种选法?–> 01背包
    请添加图片描述

  • 思路

    • 确定状态表示 -> dp[i][j]的含义

      • dp[i]j]:从前i个数中****,总和正好等于j,一共有多少种选法
    • 推导状态转移方程:根据最后一个位置的情况,分情况讨论

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

      • 多开一行及一列虚拟结点
      • 第一列除[0, 0],其余无需初始化
        • 这里第一列不会越界访问,可以交给DP阶段处理
        • 因为只有dp[i - 1][j - nums[i]]可能越界访问
          • 但是在判定后,只有j == nums[i] == 0的情况,才会进入第一列,此时又不会越界
          • 如果不符合条件,就不会进来,也不会触发越界访问
            请添加图片描述
    • 确定填表顺序:从上往下

    • 确定返回值:dp[n][a]

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


3.代码实现

// v1.0
int findTargetSumWays(vector<int>& nums, int target) 
{
    // 问题转换
    int sum = 0;
    for(auto& x : nums)
    {
        sum += x;
    }
    int aim = (sum + target) / 2;

    // 边界处理
    if(aim < 0 || (sum + target) % 2) return 0;

    int n = nums.size();
    vector<vector<int>> dp(n + 1, vector<int>(aim + 1));

    dp[0][0] = 1;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= aim; j++) // 第一列没有初始化,也在DP阶段处理
        {
            dp[i][j] = dp[i - 1][j];
            if(j >= nums[i - 1])
            {
                dp[i][j] += dp[i - 1][j  - nums[i - 1]];
            }
        }
    }

    return dp[n][aim];
}
-----------------------------------------------------------------------
// v2.0 滚动数组优化
int findTargetSumWays(vector<int>& nums, int target) 
{
    // 问题转换
    int sum = 0;
    for(auto& x : nums)
    {
        sum += x;
    }
    int aim = (sum + target) / 2;

    // 边界处理
    if(aim < 0 || (sum + target) % 2) return 0;

    int n = nums.size();
    vector<int> dp(aim + 1);

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

    return dp[aim];
}

2.最后一块石头的重量 II

1.题目链接

  • 最后一块石头的重量 II

2.算法原理详解

  • 问题转化:在数组中选择一些数,让这些数的和尽可能接近sum / 2

    • 问题转化成了目标和–> 01背包
      请添加图片描述
  • 思路

    • 确定状态表示 -> dp[i][j]的含义

      • dp[i]j]:从前i个数中****,总和不超过j,此时的最大和
    • 推导状态转移方程:根据最后一个位置的情况,分情况讨论

      • dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i])
        请添加图片描述
    • 初始化:

      • 多开一行及一列虚拟结点
      • 第一列除[0, 0],其余无需初始化
        • 这里第一列不会越界访问,可以交给DP阶段处理
        • 因为只有dp[i - 1][j - stones[i - 1]]可能越界访问
          • 但是在判定后,只有j == stones[i - 1] == 0的情况,才会进入第一列,此时又不会越界
          • 如果不符合条件,就不会进来,也不会触发越界访问
            请添加图片描述
    • 确定填表顺序:从上往下

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

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


3.代码实现

// v1.0
int lastStoneWeightII(vector<int>& stones) 
{
    int sum = 0;
    for(auto& x : stones)
    {
        sum += x;
    }

    int n = stones.size(), m = sum / 2;
    vector<vector<int>> dp(n + 1, vector<int>(m + 1));

    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= m; j++)
        {
            dp[i][j] = dp[i - 1][j];
            if(j >= stones[i - 1])
            {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - stones[i - 1]] + stones[i - 1]);
            }
        }
    }

    return sum - 2 * dp[n][m];
}
-----------------------------------------------------------------------
// v2.0 滚动数组优化
int lastStoneWeightII(vector<int>& stones) 
{
    int sum = 0;
    for(auto& x : stones)
    {
        sum += x;
    }

    int n = stones.size(), m = sum / 2;
    vector<int> dp(m + 1);

    for(int i = 1; i <= n; i++)
    {
        for(int j = m; j >= stones[i - 1]; j--)
        {
            dp[j] = max(dp[j], dp[j - stones[i - 1]] + stones[i - 1]);
        }
    }

    return sum - 2 * dp[m];
}

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

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

相关文章

推荐4个好用有趣的软件

MyComic——漫画聚合软件 MyComic是一款界面简洁、分类详尽的漫画阅读软件&#xff0c;专为动漫爱好者设计。它提供了丰富的高清漫画资源&#xff0c;支持在线免费阅读&#xff0c;并且可以一键下载到书架&#xff0c;方便随时离线观看&#xff0c;节省流量。用户可以轻松找到喜…

CSAPP Lab01——Data Lab完成思路

陪你把想念的酸拥抱成温暖 陪你把彷徨写出情节来 未来多漫长再漫长还有期待 陪伴你 一直到 故事给说完 ——陪你度过漫长岁月 完整代码见&#xff1a;CSAPP/datalab-handout at main SnowLegend-star/CSAPP (github.com) 01 bitXor 这道题是用~和&计算x^y。 异或是两个…

Android Compose 十:常用组件列表 监听

1 去掉超出滑动区域时的拖拽的阴影 即 overScrollMode 代码如下 CompositionLocalProvider(LocalOverscrollConfiguration provides null) {LazyColumn() {items(list, key {list.indexOf(it)}){Row(Modifier.animateItemPlacement(tween(durationMillis 250))) {Text(text…

接口(API)开发,测试工具-apifox

前言 为什么需要接口&#xff08;API&#xff09;? 因为不同的平台或系统可能使用不同的技术栈、编程语言或数据格式。API提供了一个标准化的方式&#xff0c;使得这些不同的系统可以相互交换数据和功能调用&#xff0c;实现互操作性 在开发日常的项目交互中&#xff0c;不…

英伟达的GPU(4)

更第四篇&#xff0c;上周有点私事&#xff0c;恢复更新 上次的文章 英伟达的GPU(3) (qq.com) 书接前文&#xff0c;我们上章说要更新GPU的内存机制&#xff0c;本次就讲点这个 先做个定义&#xff0c;我们说内存&#xff08;显存&#xff09;&#xff0c;也分物理内存&#…

Linux系统推出VB6开发IDE了?Gambas,Linux脚本编写

第一个Linux程序&#xff0c;加法计算加弹窗对话框,Gambas,linux版的类似VB6的IDE开发环境 一开始想用VB6的Clng函数转成整数&#xff0c;没这函数。 输入3个字母才有智能提示&#xff0c;这点没做好 没有msgbox函数&#xff0c;要用messagebox.warning 如果可以添加函数别名就…

【算法篇】求最长公共前缀JavaScript版本

题目描述 给你一个大小为 n 的字符串数组 strs &#xff0c;其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;返回这个公共前缀。 数据范围&#xff1a; 数据范围:0<n<5000&#xff0c;0<len(strsi)< 5000 进阶:空间复杂度 O(1)&a…

2024年第三届数据统计与分析竞赛(B题)数学建模完整思路+完整代码全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 详细请查 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024年第三届数据统计与分析竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有…

Unity | Shader基础知识(番外:了解内置Shader-Standard<一>)

目录 前言 一、什么是Standard 二、Standard参数详解 1.了解着色前 2. 着色拆分 3.参数RenderingMode 4.参数Albedo 5.参数Metallic 三、作者的话 前言 有粉丝给我说&#xff0c;感觉自己内部自带的Shader都还不知道怎么用&#xff0c;希望我讲一下内置Shader。 那…

Docker Desktop - WSL distro terminated abruptly

打开 PowerShell 或以管理员身份运行的命令提示符。运行以下命令以列出已安装的 WSL 分发&#xff1a; wsl --list 运行以下命令以注销 Docker 相关的分发 wsl --unregister <distro_name> 将<distro_name>替换为实际的 Docker 相关分发的名称。将<distro_…

[书生·浦语大模型实战营]——LMDeploy 量化部署 LLM 实践

1.基础作业 1.1配置 LMDeploy 运行环境 创建开发机 创建新的开发机&#xff0c;选择镜像Cuda12.2-conda&#xff1b;选择10% A100*1GPU&#xff1b;点击“立即创建”。注意请不要选择Cuda11.7-conda的镜像&#xff0c;新版本的lmdeploy会出现兼容性问题。其他和之前一样&…

智能组网节点是什么?

智能组网节点是一种用于解决复杂网络环境下远程连接问题的关键技术。它是一种通过智能化的方式&#xff0c;在任何网络环境下实现不同地区之间快速组建局域网的解决方案。其中&#xff0c;【天联】组网就是一款优秀的智能组网节点产品&#xff0c;是北京金万维科技有限公司自主…

苍穹外卖笔记-07-菜品管理-增加、删除、修改、查询分页还有菜品起售或停售状态

菜品管理 1 新增菜品1.1 需求分析与设计1.2 代码开发文件上传新增菜品实现 1.3 功能测试 2 菜品分页查询2.1 需求分析和设计2.2 代码开发设计DTO类设计VO类Controller层Service层Mapper层 2.3 功能测试 3 删除菜品3.1 需求分析和设计3.2 代码开发Controller层Service层Mapper层…

Unity Standard shader 修改(增加本地坐标裁剪)

本想随便找一个裁剪的shader&#xff0c;可无奈的是没找到一个shader符合要求&#xff0c;美术制作的场景都是用的都标准的着色器他们不在乎你的功能逻辑需求&#xff0c;他们只关心场景的表现&#xff0c;那又找不到和unity标准着色器表现一样的shader 1.通过贴图的透明通道做…

【set】集合总结

一、Set Set集合是Collection的子接口,代表一种集合,此种集合是元素不重复. 有两个常用实现类 HashSet 是元素不重复,无序,主要是指遍历顺序和插入顺序不一致 TreeSet 是元素不重复,排序 LinkedHashSet不常用 二、HashSet 1.1 介绍 HashSet是Set的实现类 底层是由哈希表实…

区块链(Blockchain)调查研究(一)

文章目录 1. 区块链是什么&#xff1f;2. 区块链分类和特点3. 区块链核心关键技术3.1 共识机制3.2 密码学技术3.4 分布式存储3.5 智能合约 4. 区块链未来发展趋势5. 区块链能做什么、不能做什么&#xff1f;5.1 第一部分5.2 第二部分5.3 第三部分&#xff08;结论&#xff09; …

④-1单细胞学习-cellchat单数据代码补充版

目录 1&#xff0c;数据输入及处理 ①载入包和数据 ②CellChat输入数据准备 ③构建CellChat对象 ④数据预处理 2&#xff0c;细胞通讯预测 ①计算细胞通讯概率 ②提取配受体对细胞通讯结果表 ③提取信号通路水平的细胞通讯表 ④细胞互作关系可视化 1&#xff09;细胞…

java线程相关知识点

Java多线程涉及以下几个关键点 1.线程生命周期&#xff1a;理解线程从创建到销毁的各个阶段&#xff0c;包括新建、运行、阻塞、等待、计时等待和终止。 2.线程同步&#xff1a;掌握如何使用synchronized关键字和Lock接口来同步代码&#xff0c;防止数据竞争和死锁。 3.线程间通…

csrf与xss差别 别在弄乱了 直接靶场实操pikachu的csrf题 token绕过可以吗???

我们现在来说说这2个之间的关系&#xff0c;因为昨天的我也没有弄清楚这2者的关系&#xff0c;总感觉迷迷糊糊的。 xss这个漏洞是大家并不怎么陌生&#xff0c;导致xss漏洞的产生是服务器没有对用户提交数据过滤不严格&#xff0c;导致浏览器把用户输入的当作js代码返回客户端…

HCIA--NAT地址转换(复习)

先交换后路由&#xff1a; 1&#xff1a;在交换机上创建vlan&#xff0c;进入接口划分vlan&#xff0c;接着在交换机连接路由器的接口上建立trunk干道 2&#xff1a;在路由器上&#xff0c;先配置物理接口IP&#xff0c;接着在路由器上创建两个子接口&#xff0c;将建立的vla…