刷题之动态规划-路径问题

news2024/11/25 21:41:13

前言

大家好,我是jiantaoyab,开始刷动态规划的题目了,要特别注意初始化的时候给什么值。

动态规划5个步骤

  1. 状态表示 :dp数组中每一个下标对应值的含义是什么->dp[i]表示什么
  2. 状态转移方程: dp[i] 等于什么
  3. 1 和 2 是动态规划的核心步骤,第三步是初始化,保证填表的时候不越界
  4. 填表顺序:为了保证填写当前状态的时候,所需要的状态已经计算过
  5. 返回值

第 N 个泰波那契数

image-20240327082552013

题目分析

image-20240327082930486

我们用动态规划来解决

  1. dp[i] : 表示第i个泰波那契数
  2. dp[i] = dp[i - 3] + dp[i - 2] + dp [i - 1]
  3. 初始化: dp[0] = 0; dp[1] = 1 ; dp[2] = 1;
  4. 填表顺序:从左道右
  5. 返回值:dp[n]

代码

class Solution {
public:
    int tribonacci(int n) {
      if(n == 0) return 0;
      if(n == 1 || n == 2) return 1;
      int dp[1000] = {0};
      dp[0] = 0, dp[1] = 1, dp[2] = 1;
      for(int i = 3; i <= n; i++)
      {
        dp[i] = dp[i-3] + dp[i-2] + dp[i-1];
      }
      return dp[n];
    }
};

image-20240327085917789

优化一下,可以看到只需要三个变量也能完成这个操作。

class Solution {
public:
    int tribonacci(int n) {
      if(n == 0) return 0;
      if(n == 1 || n == 2) return 1;
      int a = 0, b = 1, c = 1, d = 0;
      for(int i = 3; i <= n; i++)
      {
        d = a + b + c;
        a = b;
        b = c;
        c = d;
      }
      return d;
    }
};

三步问题

image-20240327090422340

image-20240327093241354

题目分析

  1. dp[i] :表示去到当前台阶有几种方法
  2. dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
  3. 初始化 dp[1] = 1; dp[2] = 2; dp[3] = 4;
  4. 填表顺序从左到右
  5. 返回值 d[n]

代码

class Solution {
public:
    int waysToStep(int n) {
      vector<int>dp(n + 1);
      if(n == 1 || n == 2) return n;
      if(n == 3) return 4;
      const int MOD = 1000000007;
      dp[1] = 1; dp[2] = 2; dp[3] = 4;
      for(int i = 4; i <= n; i++)
      {
        dp[i] = ((dp[i-3] + dp[i-2]) % MOD + dp[i-1]) % MOD;
      }
      return dp[n];
    }
};

使用最小花费爬楼梯

image-20240327094348136

题目分析

image-20240327102746297

  1. dp[i]:到达 i位置的最小花费
  2. dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
  3. 初始化:dp[0] = dp[1] = 0;
  4. 填表顺序:从左到右
  5. 返回值:dp[n]

代码

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
      int n = cost.size();
      vector<int> dp(n + 1);
      dp[0] = dp[1] = 0;
      for(int i = 2; i <= n; i++)
      {
        dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
      }
      return dp[n];
      
    }
};

解码方法

image-20240328121136322

题目分析

image-20240328124124445

  1. dp[i]:是表示是 i 位置为结尾的解码方法总数
  2. dp[i] = dp[i - 1] + dp [i - 2];
  3. 初始化:dp[0] = 0 / 1 dp[1] = 0/ 1/ 2
  4. 填表顺序:从左到右
  5. 返回值:dp[n - 1]

代码

class Solution {
public:
    int numDecodings(string s) {
      int n = s.size();
      vector<int> dp (n);
      
      //初始化
      dp[0] = s[0] != '0';
      if(n == 1) return dp[0];
      if(s[0] != '0' && s[1] != '0') dp[1] += 1;
      int tmp = (s[0] - '0') * 10 + (s[1] - '0');
      if(tmp >= 10 && tmp <= 26) dp[1] += 1;
      
      //处理剩下的
     for(int i = 2; i < n; i++)
     {
      //单独一个字符
        if(s[i] != '0') dp[i] += dp[i - 1];
      //2个字符
        int tmp = (s[i - 1] - '0') * 10 + (s[i] - '0');
        if(tmp >= 10 && tmp <= 26) dp[i] += dp[i - 2];
     }
      return dp[n - 1];
    }
};

优化代码

image-20240328132736524

class Solution {
public:
    int numDecodings(string s) {
      int n = s.size();
      vector<int> dp (n + 1); 
      //初始化
      dp[0] = 1;
      dp[1] = s[1 - 1] != '0';  
      //处理剩下的
     for(int i = 2; i <= n; i++)
     {
      //单独一个字符
        if(s[i - 1] != '0') dp[i] += dp[i - 1];
      //2个字符
        int tmp = (s[i - 2] - '0') * 10 + (s[i - 1] - '0');
        if(tmp >= 10 && tmp <= 26) dp[i] += dp[i - 2];
     }
      return dp[n];
    }
};

不同路径

image-20240328133027939

题目分析

image-20240328142217131

  1. dp[i] [j]:走到 i,j 位置有多少种方式
  2. dp[i] [j] = dp[i] [j - 1] + dp[i - 1] [j];
  3. 初始化:新增加一列和一行
  4. 填表顺序:从上到下,左到右填表
  5. 返回值:dp[m] [n]

代码

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m+1, vector<int>(n+1));
        //初始化
        dp[0][1] = 1;
        for(int i = 1; i <= m; i++)
        {
          for(int j = 1; j <= n; j++)
          {
            dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
          }
        }
        return dp[m][n];
    }
};

不同路径 II

image-20240328142046409

题目分析

  1. dp [i] [j] : 到达i,j这个位置有多少种方法
  2. dp [i] [j] = dp[i - 1] [j] + dp [i] [j - 1]
  3. 初始化:dp[1] [0] = 1;
  4. 填表顺序:从上到下,从左到右
  5. 返回值: dp[m] [n]

代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
          int m = obstacleGrid.size(), n = obstacleGrid[0].size();
          vector<vector<int>> dp(m + 1, vector<int>(n + 1));
          //初始化
          dp[1][0] = 1;
          for(int i = 1; i <= m; i++)
          {
            for(int j = 1; j <= n; j++)
            {
              if(obstacleGrid[i - 1][j - 1] != 1)
              dp[i][j] = dp[i - 1][j] + dp[i][j -1];
            }

          }
          return dp[m][n];
    } 
};

珠宝的最高价值

image-20240329083509134

题目分析

  1. dp [i] [j] : 到达i,j这个位置的最高价值
  2. dp [i] [j] =max(dp[i-1] [j], dp[i] [j-1]) + frame[i-1] [j-1];
  3. 初始化:默认都是0不用初始化
  4. 填表顺序:从上到下,从左到右
  5. 返回值: dp[m] [n]

代码

class Solution {
public:
    int jewelleryValue(vector<vector<int>>& frame) {
        int m = frame.size(), n = frame[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        for(int i = 1; i <= m; i++)
          for(int j = 1; j <= n; j++)
          {           
            dp[i][j] =  max(dp[i-1][j], dp[i][j-1]) + frame[i-1][j-1];
          }
        return dp[m][n];
    }
};

下降路径最小和

image-20240329090000519

题目分析

  1. dp[i] [j] : 到达i,j位置的最小下路径
  2. dp[i] [j] : min(dp[i+1] [j-1], dp[i+1] [j+1], dp[i+1] [j]) + matrix[i-1] [j - 1]
  3. 初始化:多给1行 和2列
  4. 填表顺序:从上到下,从左到右
  5. 返回值: 最后一行的最小值

image-20240329093844878

代码

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
     int n = matrix.size();
     vector<vector<int>> dp(n + 1, vector<int>(n + 2, INT_MAX));
      for(int j = 0; j < n + 2; j++) dp[0][j] = 0;
      for(int i = 1; i <= n; i++)
      {
         for(int j = 1; j <= n; j++)
        {
          dp[i][j] = min(min(dp[i-1][j-1], dp[i-1][j]), dp[i-1][j+1]) + matrix[i-1][j-1];
        }
      
      }      
      //返回值
      int ret = INT_MAX;
      for(int j = 1; j <= n; j++)
      {
        ret = min(ret, dp[n][j]);
      }
      return ret;
    }
};

最小路径和

image-20240329094117164

代码

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
        dp[1][0] = dp[0][1] = 0; 
        for(int i = 1; i <= m; i++)
          for(int j = 1; j <= n; j++)
          {
            dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i - 1][j - 1];
          }
        
      return dp[m][n];
    }
};

地下城游戏(反着来)

image-20240329102706154

题目分析

image-20240329105223745

  1. dp[i] [j] : 从i,j位置出发,到达终点所需要的最低

  2. dp[i] [j] = min(dp[i] [j + 1], dp[i + 1] [j]) - dungeon[i] [j];

  3. 初始化 dp[m +1] [n -1] = dp [m - 1] [n + 1] = 1;

  4. 填表顺序:从下到上,从右到左

  5. 返回值: dp[0] [0]

代码

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
      int m = dungeon.size(), n = dungeon[0].size();
      vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
      //初始化
      dp[m][n -1] = dp [m - 1][n] = 1;
      for(int i = m - 1; i >= 0; i--)
        for(int j = n - 1; j >= 0; j--)
        {
          dp[i][j] = min(dp[i][j + 1], dp[i + 1][j]) - dungeon[i][j];
          dp[i][j] = max(1, dp[i][j]); //如果血包很大,会出现负数,这里取1就是最低血
          
        }
        return dp[0][0];
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python毕业设计django宠物寄存系统fn62p

本文所设计的宠物寄存中心系统的设计与实现拥有前端和后端&#xff0c;前端使用Vue.js框架和创建&#xff0c;后端使用django框架创建&#xff0c;开发语言采用python&#xff0c;使用Mysql数据库对后台数据进行存储。将pcyahrm作为主要的开发工具。接着进行系统的需求分析、功…

surfer绘制等值线图

surfer介绍 Surfer软件&#xff0c;是美国Golden Software公司编制的一款以画三维图的软件。该软件具有强大的插值功能和绘制图件能力&#xff0c;可用来处理XYZ数据&#xff0c;是地质工作者常用的专业成图软件&#xff08;来源于百度百科&#xff09;。 surfer可以用来绘制…

Linux文件与进程交互的窥探者lsof

lsof 是一个 Linux 和 UNIX 系统中的实用工具,用于列出系统中打开文件的所有信息。这个名字代表 “List Open Files”,但它也可以显示进程相关的其他信息,如: 打开的文件描述符列表 打开网络连接的列表 被进程使用的信号和内核对象等 在Linux系统中,有一个经典的概念: …

NOSQL - Redis的简介、安装、配置和简单操作

目录 一. 知识了解 1. 关系型数据库与非关系型数据库 1.1 关系型数据库 1.2 非关系型数据库 1.3 区别 1.4 非关系型数据库产生背景 1.5 NOSQL 与 SQL的数据记录对比 2. 缓存相关知识 2.1 缓存概念 2.2 系统缓存 2.3 缓存保存位置及分层结构 二 . redis 相关知识 1.…

【MySQL】13. 索引(重点)

1. 没有索引&#xff0c;可能会有什么问题 索引&#xff1a;提高数据库的性能&#xff0c;索引是物美价廉的东西了。 不用加内存&#xff0c;不用改程序&#xff0c;不用调sql&#xff0c;只要执行正确的 create index &#xff0c;查询速度就可能提高成百上千倍。 但是天下没…

如何提高小红书笔记的收录率?

在小红书平台上&#xff0c;笔记的收录率是衡量一篇笔记是否受欢迎和有价值的重要因素。为了提高笔记的收录率&#xff0c;有几个关键点需要注意&#xff1a; 1.内容不涉及广告 在发布笔记前要先确保笔记内容不包含任何形式的广告或推广信息。小红书平台对于广告性质的内容有…

关于 HEAP CORRUPTION DETECTED:after Normal block 错误的原因及解析

目录 一、HEAP CORRUPTION DETECTED:after Normal block 出现的报错情况&#xff1a; 二、问题原因&#xff08;重要&#xff09;&#xff1a; 三、举例 1.错误代码如下&#xff1a; 2.错误原因及分析&#xff08;重要&#xff09;&#xff1a; 3.解决方法 ​编辑 4.正…

OMP压缩感知仿真(MATLAB)

clc; clearvars; close all;% 读文件 Ximread(mandrill256.bmp); tic; Xdouble(X); [m,n]size(X);% % 小波变换矩阵生成 [LL1, LH1, HL1, HH1] dwt2(X, haar); [LL2, LH2, HL2, HH2] dwt2(LL1, haar); % [LL3, LH3, HL3, HH3] dwt2(LL2, haar); % [LL4, LH4, HL4, HH4] d…

Demis Hassabis,这位被封为爵士的AI领域的杰出研究者和神经科学家,是否能成为Google的救星?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Jquery——js库

1. jQuery 基础操作 jQuery 是一个快速、小巧的 JavaScript 库&#xff0c;设计用于简化 HTML 文档的遍历、事件处理、动画设计和 Ajax 交互。jQuery 使用户能够更快地编写 JavaScript 代码&#xff0c;并且能够更容易地处理 HTML 文档、事件、动画和 Ajax。 加载 jQuery 要…

HDLbits 刷题 -- Alwaysblock2

学习&#xff1a; For hardware synthesis, there are two types of always blocks that are relevant: Combinational: always (*)Clocked: always (posedge clk) Clocked always blocks create a blob of combinational logic just like combinational always blocks, but…

【DETR系列目标检测算法代码精讲】01 DETR算法03 Dataloader代码精讲

与一般的Dataloader的区别在于我们对图像进行了随机裁剪&#xff0c;需要进行额外的操作才能将其打包到dataloader里面 这一段的代码如下&#xff1a; if args.distributed:sampler_train DistributedSampler(dataset_train)sampler_val DistributedSampler(dataset_val, shu…

LeetCode-48. 旋转图像【数组 数学 矩阵】

LeetCode-48. 旋转图像【数组 数学 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;一行代码&#xff01;Python zip函数图一乐【zip函数实现主对角线翻转&#xff0c;[::-1]实现垂直翻转】解题思路二&#xff1a;其实我们也可以先水平轴翻转&#xff0c;让后主对角线翻转。…

Linux之用户账号、用户组和与账号有关的系统文件

目录 一、基本介绍 1.用户和用户组 2.UID和GID 二、 账户管理 1.查看用户的UID和GID 2.添加账户 3.删除账号 4.修改账号 5.账户口令 三、分组管理 1.新增用户组 2.删除用户组 3.修改用户组 4.用户组切换 四、与账号有关的系统文件 1./etc/passwd 2./etc/shado…

LeetCode_33_中等_搜索旋转排序数组

文章目录 1. 题目2. 思路及代码实现详解&#xff08;Python&#xff09;2.1 二分查找 1. 题目 整数数组 n u m s nums nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c; n u m s nums nums 在预先未知的某个下标 k &#xff08; 0 < k…

python_绘图_多条折线图绘制_显示与隐藏

1. 需求 给定一个二维数组 100行, 5列, 每一列绘制一条折线, 横轴为行索引, 纵轴为对应位置的值, 绘制在一个子图里面, 使用python plot, 使用随机颜色进行区别添加显示和隐藏按钮, 可以对每条折线进行显示和隐藏 2. 代码 import numpy as np import matplotlib.pyplot as p…

使用Docker快速搭建Kafka

前言 今天讲下如何使用Docker快速搭建kafka。 前期准备&#xff0c;需要安装好docker、docker-compose。 一、安装Kafka 1、创建Kafka目录&#xff0c;执行如下命令。 mkdir -p /docker/kafka/ cd /docker/kafka/ 2、编写yaml文件&#xff0c;内容如下。 vim docker-com…

国产桌面操作系统统一身份认证及2FA双因子认证安全升级方案

某金融运营服务公司&#xff0c;主要负责业务处理、客户服务、业务监控、报表统计等金融运营服务&#xff0c;为集团下设二级单位&#xff0c;坐落于一线城市&#xff0c;对政策风向有很高的敏锐度。 该公司已为公司业务人员、客户服务、监督员等配备了数百台国产桌面操作系统…

springboot 将manage关闭。

这是SpringBoot自带的接口&#xff0c;会将所有的接口暴露在外面。所以我们上生产环境&#xff0c;需要将这个接口给关闭。 默认是 management.endpoints.web.exposure.include* 只需将配置文件改成下面&#xff0c;Springboot自带的接口就会关闭。 management.endpoints.…

嵌入式系统基础知识(一):嵌入式系统是什么?

一.定义 根据IEEE&#xff08;国际电气和电子工程师协会&#xff09;的定义&#xff0c;嵌入式系统是“控制、监视或者辅助设备、机器和车间运行的装置”。这主要是从应用上加以定义的&#xff0c;从中可看出嵌入式系统是软件和硬件的综合体&#xff0c;还可以涵盖机械等附属装…