二维DP问题

本文探讨二维动态规划(DP)问题,从基础概念到解决实际例题,包括经典问题如独特路径、独特路径II和最小路径和。通过小技巧避免边界问题,以及将二维DP数组压缩为一维,讲解如何找到最优子结构并应用动态规划求解。
摘要由CSDN通过智能技术生成

前言

我们经常会碰到二维DP问题,比如给你一张地图(一般是二维矩阵),让你计算出从地图的左上端走到右下端的路径有多少条 / 最短的路径之和,这种问题一般会被限制运动的空间(至少我现在所碰到的题目),一般是只能向下和向右移动。

我对dp问题理解不深,对于二维dp问题我的理解就是找出最优子结构(递推方程)之后,用一个二维数组来保存历史状态就能解决问题了

小技巧

一般这种问题很容易被矩阵上边和左边这两条boundary把程序搞得很复杂(因为这两个boundary需要修改特定的递推公式程序),我们在开辟二维dp数组时,把长和宽都+1,然后从(i,j)=(1,1)开始遍历,这样就不会遇到boundary问题了

其次就是dp数组压缩,我们可以观察到,其实我们的二重嵌套循环就是每次循环一行,然后对于这一行的每一个元素,都根据他的dp[left]dp[up]来对他进行更新,而我们可以使用一个映射,将这种二维关系(dp[left]dp[up])映射成一维关系(意思就是我们只用使用一个一维的DP数组即可)

比如

if col == 0
	dp[col] = f(dp[col])// 这是因为现在的dp[up]就是dp[col],而col=0时,dp[col]的左边没东西
else 
	dp[col] =  f(dp[col-1], dp[col])//这是因为此时 dp[left] = dp[col-1], dp[up] = dp[col]

通过上面的伪代码,你一定明白了如何将二维dp数组压缩为一维dp数组吧

例题 1

这是非常经典的一道二维dp题目了,我们的解决方法有两种:求组合数DP求解

DP求解的话,这个问题的最优子结构为:
d p [ c u r r ] = d p [ l e f t ] + d p [ u p ] dp[curr] = dp[left] + dp[up] dp[curr]=dp[left]+dp[up]

62. Unique Paths
There is a robot on an m x n grid. The robot is initially located at the top-left corner (i.e., grid[0][0]). The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either down or right at any point in time.

Given the two integers m and n, return the number of possible unique paths that the robot can take to reach the bottom-right corner.

The test cases are generated so that the answer will be less than or equal to 2 * 109.

Example 1:
在这里插入图片描述

Input: m = 3, n = 7
Output: 28
Example 2:

Input: m = 3, n = 2
Output: 3
Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Down -> Down
2. Down -> Down -> Right
3. Down -> Right -> Down

方法一 求组合数

因为机器人只能向右或者向下走,而机器人一共要走 width + height 步,所以总的走法就是一个组合数 : C(n, m),其中n为height+weight, m为weight或者height

class Solution {
   
public:
    int uniquePaths(int m, int n) {
   
        if(m == 1 || n == 1)
            return 1;
        m--, n--;
        if(m < n) swap(m, n);
        long res = 1;
        for(int i = m+1, j=1; i <= m+n; i++, j++){
          // Instead of taking factorial, keep on multiply & divide
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值