Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)

Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)

动态规划应该如何学习?-CSDN博客

01背包模板 | 学习总结-CSDN博客

完全背包模板总结-CSDN博客

难点:

代码都不难写,如何想到完全背包并把具体问题抽象为完全背包才是关键

文章目录

  • Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
    • 377.组合总和IV
      • 思路分析:
      • 难点讲解
        • 1.为什么这样可以求出来排列数量?
        • 2.dp数组如何初始化,我们应该如何理解初始化
      • 1.动态规划
      • 2.回溯法
      • 3.记忆化搜索
    • 到这里我们会发现,这里的dp不就是先遍历背包容量后遍历物品的完全背包吗?
      • 组合
      • 排列

377.组合总和IV

377. 组合总和 Ⅳ - 力扣(LeetCode)

思路分析:

虽然说是组合,但本质是求的排列,要考虑元素的顺序

代码随想录只是说了一下遍历顺序不同,可以分别求出排列数量和组合数量,但大家肯定还是不太清楚。还是看看灵神的题解怎么说吧。

本题其实就是 70. 爬楼梯,我们每次从 nums 中选一个数,作为往上爬的台阶数,问爬 target 个台阶有多少种方案。70 那题可以看作 nums=[1,2],因为每次只能爬 1 个或 2 个台阶。

dp[i]的含义就是爬上第i个台阶的方案数量

1.在那道题中

我们的代码是

dp[i]=dp[i-1]+dp[i-2]

2.如果说我们一次可以爬k个台阶,当然k要比target(要爬的总楼梯数量)小

dp[i]=dp[i-1]+dp[i-2]+dp[i-3]+....+dp[i-k]
//等价于
for(int j=1;j<=k;j++)dp[i]+=dp[i-j];

3.如果说我们一次可以爬的台阶数量是nums数组里面的,那么j就是nums[j],上面的1-k就相当于这里的nums数组的遍历

dp[i]=dp[i-nums[1]]+dp[i-nums[2]]+dp[i-nums[3]]+....+dp[i-nums[nums.size()-1]]
//等价于
for(int j=0;j<nums.size();j++)dp[i]+=dp[i-nums[j]];

相当于,在第一种情况中

nums数组为{1,2}

在第二种情况中

nums数组为{1,2,3,…,k}

难点讲解

1.为什么这样可以求出来排列数量?

举个例子,我们要登上台阶3(target=3)

我们的nums数组为{1,2}

那很显然我们dp[3]=dp[1]+dp[2]了

就是从第一个台阶一次爬2个(1,2先爬一个再爬两个)

和从第二个台阶一次爬1个(2,1先爬两个再爬一个)

很明显,可以是排列的原因就是,我们在爬每一个台阶往上爬看能不能看target的时候会从nums的数组的第一个元素开始重新遍历,会把所有的元素重新遍历一遍

2.dp数组如何初始化,我们应该如何理解初始化
dp[0]=1;

要知道这道题是达到target就行

假如我们nums里面有一个值就是target

那岂不是直接就会有一种方案是从0到target

而我们的递推公式里面有这个情况

dp[target]=…+dp[target-target](这个值就是dp[0])

这个方案数量为1,除此之外呢不会有其他的情况可以取到这个值

这个初始化和下面代码等价

for(int i=0;i<nums.size();i++)if(nums[i]<=target)dp[nums[i]]=1;

为什么是等价的呢?

如果dp[0]没有初始化为1

那dp[nums[i]]=…+dp[nums[i]-nums[i]]里面的最后一项就是dp[0]=0,你发现就少加了一个1

而我们初始化的时候上面的这三行代码已经把它初始化成1了,dp[0]=0也就无所谓了

所以两种初始化方式都可以

而用回溯法递归的话,dp[0]=1可以理解为是我们从target开始向下爬,可以爬到0,那就是找到了一个合法的方案,我们就会返回1

1.动态规划

既然递推公式和初始化全想清楚了,那就直接上动态规划,完了再想回溯和记忆化搜索

1.确定dp数组以及下标的含义

dp[i]: 凑成目标正整数为i的排列个数为dp[i]

也就是上面说的爬到第i个台阶有多少种方法

2.确定递推公式

正如上面爬楼梯所说的

for(int j=0;j<nums.size();j++)dp[i]+=dp[i-nums[j]];

3.dp数组如何初始化

请看难点讲解2

4.确定遍历顺序

外层循环遍历台阶i

内层循环nums数组

都是从前往后遍历

完整代码:

啊,i>=nums[j]是因为你一次爬(nums[j])的总不能比要爬的总数(i)高了吧

class Solution {
public:int combinationSum4(vector<int>& nums, int target) {vector<unsigned> dp(target+1,0);/*for(int i=0;i<nums.size();i++)if(nums[i]<=target)dp[nums[i]]=1;*/dp[0]=1;for(int i=1;i<=target;i++)for(int j=0;j<nums.size();j++)if(i>=nums[j])dp[i]+=dp[i-nums[j]];return dp[target];}
};

2.回溯法

我们从第c个台阶往第0个台阶走

能到达第0个台阶那就是找到了一个合法的方案

到不了就是没找到一个合法的方案

1.参数和返回值

c是要爬的第几个台阶

nums是我们一次可以爬几个台阶

dfs返回的就是我们爬到c可以有几个方案

int dfs(int c,vector<int>& nums)

2.终止条件

如果c==0,说明我们可以从target向下走到底

说明找到了一个合法的方法,返回1

if(c==0)return 1;

3.本层逻辑

动态规划两层for循环,那么在递归函数里面就需要一个for循环,另外一层循环由递归体现

还是一样的,爬到c的方法就是,从c-num[0],c-nums[1]…c-nums[i]这些台阶爬到c的方案数量相加

		int res=0;for(int i=0;i<nums.size();i++)if(c>=nums[i])res+=dfs(c-nums[i],nums);return res;

完整代码:

当然是超时的

class Solution {
public:int dfs(int c,vector<int>& nums){if(c==0)return 1;int res=0;for(int i=0;i<nums.size();i++)if(c>=nums[i])res+=dfs(c-nums[i],nums);return res;}int combinationSum4(vector<int>& nums, int target) {return dfs(target,nums);}
};

3.记忆化搜索

就是还是全都初始化为-1,每次返回前给dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了

完整代码:

class Solution {
public:int dfs(int c,vector<int>& nums,vector<unsigned>& dp){if(c==0)return 1;int res=0;if(dp[c]!=-1)return dp[c];for(int i=0;i<nums.size();i++)if(c>=nums[i])res+=dfs(c-nums[i],nums,dp);return dp[c]=res;}int combinationSum4(vector<int>& nums, int target) {vector<unsigned> dp(target+1,-1);return dfs(target,nums,dp);}
};

到这里我们会发现,这里的dp不就是先遍历背包容量后遍历物品的完全背包吗?

所以先遍历物品,后遍历背包容量 得到的就是nums能凑成target的组合

先遍历背包容量,后遍历物品 得到的就是nums能凑成target的排列

组合

经典题目零钱兑换II

Day39 | 动态规划 :完全背包应用 零钱兑换&&零钱兑换II-CSDN博客

排列

本次题解的组合总和IV

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序——用户隐私保护指引填写(详细版)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【在Linux世界中追寻伟大的One Piece】poll代码改写

目录 1 -> poll代码改写 1 -> poll代码改写 结合select代码&#xff0c;将select server更改成为pollserver&#xff0c;不是一件困难的事情。 #pragma once#include <iostream> #include <string> #include <poll.h> #include <memory> #inc…

安利一款开源企业级的报表系统SpringReport

SpringReport是一款企业级的报表系统&#xff0c;支持在线设计报表&#xff0c;并绑定动态数据源&#xff0c;无需写代码即可快速生成想要的报表&#xff0c;可以支持excel报表和word报表两种格式&#xff0c;同时还可以支持excel多人协同编辑&#xff0c;后续考虑实现大屏设计…

【11月10日最新】V2.6.1版本植物大战僵尸杂交版分享与下载

&#x1f447;下载链接&#xff1a; 点击下载 更新内容 植物大战僵尸杂交版2.6.1版本的更新内容主要包括以下几个方面&#xff1a; 梦幻联动&#xff1a; 与UP主轻柔北风合作&#xff0c;推出了“植物大战僵尸贴吧版”。联动植物包括石果子与雷蘑菇杂交的雷果子&#xff0c;…

Jenkins找不到maven构建项目

有的可能没有出现maven这个选项 解决办法&#xff1a;需要安装Maven项目插件 输入​Maven Integration plugin​

路过宝安乌石岩庙记

​每周带娃从上屋地铁去罗租大道的七彩城堡儿童乐园玩&#xff0c;路上都会经过乌石岩庙附近。听说香火很繁盛&#xff0c;娃说也想去看看&#xff0c;于是来到了乌石岩庙。 石岩乌石岩庙 广东省深圳市宝安区老街一区94号 ​从百度知悉&#xff1a;乌石岩庙&#xff0c;又称“…

练习LabVIEW第四十四题

学习目标&#xff1a; 计算学生三门课(语文&#xff0c;数学&#xff0c;英语)的平均分&#xff0c;并根据平均分划分成绩等级。要求输出等级A,B,C,D,E。90分以上为A&#xff0c;80&#xff5e;89为B&#xff0c;70&#xff5e;79为C&#xff0c;60&#xff5e;69为D&#xff…

软考高级架构 - 8.1 - 系统质量属性与架构评估 - 超详细讲解+精简总结

第8章 系统质量属性与架构评估 软件系统属性包括功能属性和质量属性&#xff0c;而软件架构重点关注质量属性。 8.1 软件系统质量属性 8.1.1 概述 软件系统的质量反映了其与需求的一致性&#xff0c;即&#xff1a;软件系统的质量高低取决于它是否能满足用户提出的需求&#…

最详细【Elasticsearch】Elasticsearch Java API + Spring Boot集成 实战入门(基础篇)

Elasticsearch Java API Spring Boot集成 实战入门&#xff08;基础篇&#xff09; 一、初始Elasticseach1、什么是Elasticseach2、Elasticsearch生态2、Elasticsearch结构3、Elasticsearch核心概念4、Elasticsearch 实现全文检索的原理 二、Elasticsearch入门1、入门-环境安装…

类文件结构详解

回顾一下字节码 在 Java 中&#xff0c;JVM 可以理解的代码就叫做字节码&#xff08;即扩展名为 .class 的文件&#xff09;&#xff0c;它不面向任何特定的处理器&#xff0c;只面向虚拟机。Java 语言通过字节码的方式&#xff0c;在一定程度上解决了传统解释型语言执行效率低…

RabbitMQ的应用

七种工作模式介绍 1.Simple(简单模式) P&#xff1a;生产者&#xff0c;也就是要发送信息的程序 C&#xff1a;消费者&#xff0c;消息的接收者 Queue&#xff1a;消息队列。图中黄色背景部分&#xff0c;类似一个邮箱&#xff0c;可以缓存发送信息&#xff1b;生产者向其中…

科研绘图系列:R语言组合堆积图(stacked plot)

文章目录 介绍加载R包数据数据预处理画图1画图2组合图形系统信息介绍 堆积图(Stacked Chart),也称为堆叠图,是一种常用的数据可视化图表,主要用于展示不同类别的数据量在总体中的分布情况。堆积图可以是柱状图、条形图或面积图的形式,其中各个类别的数据量被叠加在一起,…

测试概念以及测试bug

关于测试的概念 什么是需求&#xff1f; 需求分为用户需求和软件需求。 软件需求可以作为开发和测试工作的依据&#xff0c;而用户需求不一定是合理的&#xff0c;这里的不合理有很多的角度&#xff1a;技术角度上&#xff0c;市场需求上&#xff0c;投入成本和收益比噔噔。…

单体架构的 IM 系统设计

先直接抛出业务背景&#xff01; 有一款游戏&#xff0c;日活跃量&#xff08;DAU&#xff09;在两千左右&#xff0c;虽然 DAU 不高&#xff0c;但这两千用户的忠诚度非常高&#xff0c;而且会持续为游戏充值&#xff1b;为了进一步提高用户体验&#xff0c;继续增强用户的忠…

Node.js——fs模块-文件删除

1、在Node.js中&#xff0c;我们可以使用unlink或unlinkSync来删除文件。 2、语法&#xff1a; fs.unlink(path,callback) fs.unlinkSync(path) 参数说明&#xff1a; path 文件路径 callback 操作后的回调函数 本文的分享到此结束&#xff0c;欢迎大家评论区一同讨论学…

Halcon 从XML中读取配置参数

1、XML示例 以下是一个XML配置文件的示例,该文件包含了AOI(自动光学检测)算法的环境参数和相机逻辑参数: <AOI><!--AOI算法参数 20241106--><Env><!--环境参数--><Param name="GPUName" value="NVIDIA GeForce RTX 405…

数据冒险-add x1, x1, x2 add x1, x1, x3 add x1, x1, x4

第一张图没有传递机制 竞争情况分析 读后写&#xff08;RAW&#xff09;竞争&#xff1a;当某条指令需要读取一个寄存器的值&#xff0c;而该寄存器的值尚未被前面的指令写入时&#xff0c;就会发生这种竞争。 指令2&#xff08;dadd r1, r1, r3&#xff09;依赖于指令1&#…

leetcode138:随机链表的复制

给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新节点的 n…

使用 Umami 部署博客分析工具

Umami 简介 Umami 是一款开源且注重隐私的网站分析工具&#xff0c;可替代 Google Analytics。它提供网站流量和用户行为等见解&#xff0c;但不使用 Cookie 或收集个人数据&#xff0c;符合隐私法规。Umami 轻巧易用&#xff0c;可自行托管。 如果你有自己的博客&#xff0c;…

巡检任务管理系统(源码+文档+部署+讲解)

本文将深入解析“巡检任务管理系统”的项目&#xff0c;探究其架构、功能以及技术栈&#xff0c;并分享获取完整源码的途径。 系统概述 巡检任务管理、巡检抽查、巡检任务随机分派等功能 本项目名称为巡检管理系统&#xff0c;是对巡检工作进行数字化管理的系统。该系统适用…