动态规划刷题指南(超级简单易懂)持续更新

这篇博客详细介绍了动态规划的解题思路,通过分析LeetCode上的Maximum Subarray、Minimum Path Sum和Unique Paths等经典问题,阐述了动态规划的基本原理和常见应用场景。博主逐步解析了每个问题的动态规划方程,并提供了代码实现。此外,还探讨了如何将动态规划与分治法结合,以及如何处理复杂问题,如动态规划在编码解码问题中的应用。
摘要由CSDN通过智能技术生成
  1. Maximum Subarray
    https://leetcode.com/problems/maximum-subarray/description/
    Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Follow up: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

contiguous adj. 连续的;邻近的;接触的
subarray :n. 子阵列;子数组
divide 分治,v. (使)分开,分成;分配,分担;分隔;(道路)分叉;使产生分歧;(数)除,除以
subtle :adj. 微妙的;精细的;敏感的;狡猾的;稀薄的


题目的意思就是,给一个整型数组,找到相邻的一段数据(至少一个元素)是最大和的子数组,并返回这个最大和.

后续:如果您已经找到了O(n)解决方案,那么尝试使用分治法编写另一个解决方案,后者更加微妙。
题解:
这就是最基础的dp,最开始做的dp就长这个样子,我们要算数组中的最大值 ,相当于算0-n的这段的最大值,相当于算0-n-1这段的最大值,然后在加上(或者不加最后一个),相当于算0-n-2中的最大值,然后再觉得加还是不加a[n-1],所以dp就出来了 f[i],设f[i],为前i个数的最大值,则,动态方程就出来了:
f[i] = max(f[i-1]+a[i] , a[i]) 当然还有细节要处理.这里先不管来推一次: 其实我觉得我这里的推到过程不是很详细,我们可以这样看 :

在这里插入图片描述

f(0) =max(0,a[0]);
f(1) = max(f[0]+a[1] , a[1]);
f(2) = max(f[1]+a[2], a[2]);

这样我们就把包括a[n]的所有的最大子序和算出来了,然后找到最大值返回就行了

代码:

class Solution {
   
public:
    int maxSubArray(vector<int>& a) {
   
         
        int size = a.size();
        if(size == 0) return 0;
        int f[20003] , maxn = a[0];
        f[0] = max(0,a[0]);
        for(int i=1;i<size ; i++ )
        {
   
            f[i] = max(f[i-1]+a[i] , a[i]);//算出每个包括ai的最大的自诩和
            if(maxn<f[i]) maxn = f[i];
        }
        return maxn;
    }
};
  1. Minimum Path Sum
    https://leetcode-cn.com/problems/minimum-path-sum/
    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Example:

Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.
翻译:
grid :n. 网格;格子,栅格;输电网
top left to bottom righ :左上角到右下角
all numbers along its path.:路径上的和


最短路径,
给你一个m*n的网格,填满了非负整数,找到一个从左上角到右下角的路径,使得路径上的的数字和最小.
说明:你只能向下或者想右移动

题解::
虽然不知道怎么回事但是,但是由于最近在练习dp,所以要用dp思路: 由于我们要找左上到右下的 ,那我们把到每个地方的路径和求出来就行,因为只能像右和下走,所以,我们到左和下的全都标记为1(因为只能有一种方法到达),

在这里插入图片描述
找到每种方法用掉路径值最小的方法.
动态方程:
f[0][0]=a[0][0];
f[ 1][0] = f[0][0]+a[1][0];
f[ 2][0] = f[1][0]+a[2][0];
f[ 3][0] = f[2][0]+a[3][0];

f[0][1] = f[0][0]+a[0][1];
f[0][2] = f[0][1]+a[0][2];
f[0][3] = f[0][2]+a[0][3];
f[0][4] = f[0][3]+a[0][4];
f[0][5] = f[0][4]+a[0][5];
f[0][6] = f[0][5]+a[0][6];
//初始化成功:

f[i[j] =min(f[i-1][j] ,f[i][j-1])+a[i][j];//他们两个中间的最小值

class Solution {
   
public:
    int minPathSum(vector<vector<int>>& grid) {
   
     int size_row = grid.size();  //获取行数
     int size_col = grid[0].size();  //获取列数
     int f[1000][1000];
    f[0][0] =grid[0][0];
    for(int i = 1;i<size_row ;i++)
    {
   
        f[i][0] = grid[i][0]+f[i-1][0];
//        cout<<f[i][0]<<endl;
    }
//cout<<endl;
    for(int i = 1;i<size_col ;i++)
    {
   
        f[0][i] = grid[0][i]+f[0][i-1];
//        cout<<f[0][i]<<endl;
    }
//cout<<endl;        
    for(int i = 1;i<size_row ;i++)
    {
   
      for(int j = 1;j<size_col ;j++)
    {
   
          
        f[i][j] = min(f[i-1][j] +grid[i][j] , f[i][j-1]+grid[i][j]);
//          cout<<f[i][j]<<endl;
    }
    
    }
    return f[size_row-1][size_col-1];
    }
};
  1. Unique Paths
    https://leetcode-cn.com/problems/unique-paths/

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

How many possible unique paths are there?

一个机器人在左上角,在下图中标记为开始,然后这个机器人智能向下或者像右走一个点,这个机器人想要到达右下角的格子,下图中标记finish的格子,有多少可能的路径在这里?

在这里插入图片描述
其实这个题也很简单,简单的dp就可,因为我们要算到右下角的位置,所以要先到右下角的前一个位置,因为只能是像右和下移动,所以我们只能是从上或者左方的格子来到当前位置的.所以到达右下角的路径个数就是从左方和上方的和.

大致的过程就如图:
在这里插入图片描述
因为只能向右和下走,所以右方和下方全为1,只有一种到达的可能,其他的地方可能是他的上方或者左方到达的
所以,到达此地方的路径数就是f[i-1][j]+f[i]j-1]
所以动态方程就出来了:
f[i][j] = f[i-1][j]+f[i]j-1];
代码:

class Solution {
   
public:
    int uniquePaths(int m, int n) {
   
    if(m=
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值