我在代码随想录|写代码Day33 | 动态规划| 路径问题| 62.不同路径,63. 不同路径 II,343. 整数拆分

🔥博客介绍`: 27dCnc

🎥系列专栏: <<数据结构与算法>> << 算法入门>> << C++项目>>

🎥 当前专栏: << 算法入门>>

专题 : 数据结构帮助小白快速入门算法
👍👍👍👍👍👍👍👍👍👍👍👍
☆*: .。. o(≧▽≦)o .。.:*☆

❤️感谢大家点赞👍收藏⭐评论✍️

学习目标:

今日学习打卡

  • 代码随想录 – 动态规划

学习时间:

  • 周一至周五晚上 7 点—晚上9点
  • 周六上午 9 点-上午 11 点
  • 周日下午 3 点-下午 6 点

学习内容:

  1. 不同路径
  2. 不同路径 II
  3. 整数拆分

内容详细:

62.不同路径

考点: 动态规划 数学 深度优先搜索(dfs)

解题思路
高中时候的组合规律,当然我们不能直接这样写我们要进行动态规划分析

首先看到题目是想到dfs

class Solution {
private:
    int dfs(int i, int j, int m, int n) {
        if (i > m || j > n) return 0; // 越界了
        if (i == m && j == n) return 1; // 找到一种方法,相当于找到了叶子节点
        return dfs(i + 1, j, m, n) + dfs(i, j + 1, m, n);
    }
public:
    int uniquePaths(int m, int n) {
        return dfs(1, 1, m, n);
    }
};

但是超时

开始动态规划

  1. 确定dp数组以及下标的含义
dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。
  1. 确定递推公式(到这一步的方式)

想要求dp[i][j],只能有两个方向来推导出来,即dp[i – 1][j] 和 dp[i][j – 1]。

此时在回顾一下 dp[i – 1][j] 表示啥,是从(0, 0)的位置到(i – 1, j)有几条路径,dp[i][j – 1]同理。

那么很自然,dp[i][j] = dp[i – 1][j] + dp[i][j – 1],因为dp[i][j]只有这两个方向过来。

  1. dp数组的初始化
    这个就是高中的知识点
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
  1. 确定遍历顺序
    这里要看一下递推公式dp[i][j] = dp[i – 1][j] + dp[i][j – 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。

这样就可以保证推导dp[i][j]的时候,dp[i – 1][j] 和 dp[i][j – 1]一定是有数值的。

  1. 举例推导dp数组

    最终代码
class Solution {
public:
    int uniquePaths(int m, int n) {
        int dp[m][n];
        dp[0][0] = 0;
        for (int i = 0; i < m; i++) dp[i][0] = 1;
        for (int j = 0; j < n; j++) dp[0][j] = 1;
        for (int i = 1;i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i-1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};

63. 不同路径 II

题目考点: 动态规划

解题思路
和上一题一样,只是多了障碍物,可以直接跳过,
如果遇到障碍物 continue

if (obstacleGrid[i][j] == 1) {continue;}

i 代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int l,r;
        int m =obstacleGrid.size();
        int n = obstacleGrid[0].size();
        int dp[m][n];
        if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1){
            return 0;
        }
        memset(dp,0,sizeof(dp));
        for (int i = 0; i < m && !obstacleGrid[i][0]; i++) dp[i][0] = 1;
        for (int j = 0; j < n && !obstacleGrid[0][j]; j++) dp[0][j] = 1;
        for (int i = 1;i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] == 1) {continue;}
                dp[i][j] = dp[i-1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};

ii 代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if (obstacleGrid[0][0] == 1)
            return 0;
        vector<int> dp(obstacleGrid[0].size());
        for (int j = 0; j < dp.size(); ++j)
            if (obstacleGrid[0][j] == 1)
                dp[j] = 0;
            else if (j == 0)
                dp[j] = 1;
            else
                dp[j] = dp[j-1];

        for (int i = 1; i < obstacleGrid.size(); ++i)
            for (int j = 0; j < dp.size(); ++j){
                if (obstacleGrid[i][j] == 1)
                    dp[j] = 0;
                else if (j != 0)
                    dp[j] = dp[j] + dp[j-1];
            }
        return dp.back();
    }
};

343. 整数拆分

题目考点: 动态规划

解题思路

可以拆分成多个数据对动态规划实行贪心,max就是贪心的具象化,(个人理解)

其他步骤省,这里详细讲解

  • 确定递推公式

可以想 dp[i]最大乘积是怎么得到的呢?

其实可以从1遍历j,然后有两种渠道得到dp[i].

一个是j * (i – j) 直接相乘。

一个是j * dp[i – j],相当于是拆分(i – j),对这个拆分不理解的话,可以回想dp数组的定义。

那有同学问了,j怎么就不拆分呢?

j是从1开始遍历,拆分j的情况,在遍历j的过程中其实都计算过了。那么从1遍历j,比较(i – j) * j和dp[i – j] * j 取最大的。
递推公式:

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

也可以这么理解,j * (i – j) 是单纯的把整数拆分为两个数相乘,而j * dp[i – j]是拆分成两个以及两个以上的个数相乘。

  • 如果定义dp[i – j] * dp[j] 也是默认将一个数强制拆成4份以及4份以上了。

  • 所以递推公式:dp[i] = max({dp[i], (i – j) * j, dp[i – j] * j});

  • 那么在取最大值的时候,为什么还要比较dp[i]呢?

因为在递推公式推导的过程中,每次计算dp[i],取最大的而已。

class Solution {
public:
    int integerBreak(int n) {
        if(n < 4) return n/2 * (n - n/2);
        int dp[n+4];
        memset(dp,0,sizeof dp);
        dp[2] = 1;
        for (int i = 3; i <= n ; i++) {
            for (int j = 1; j <= i / 2; j++) {
                dp[i] = max({dp[i], (i - j) * j, dp[i - j] * j});
            }
        }
        return dp[n];
    }
};

学习产出:

  • 技术笔记 2 遍
  • CSDN 技术博客 3 篇
  • 习的 vlog 视频 1 个

重磅消息:

GTP – 4 最新版接入服务他来了 点击链接即可查看详细

GTP – 4 搭建教程

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~

版权声明:本文为博主作者:EvLast原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/2303_79299383/article/details/136464707

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2024年4月16日
下一篇 2024年4月16日

相关推荐