【算法】C++动态规划+滚动数组(面试极其加分的代码)

动态规划(Dynamic Programing)

  • 一、DP思路
  • 二、题解步骤
  • 三、例题
  • 四、滚动数组初体验(DP问题空间优化)

一、DP思路

  • 看到OJ题需要求最值,就应该形成条件反射——嗯,这题或许要使用贪心算法或者动态规划。当你发现贪心不能解决问题,且原问题规模可缩小时,即可考虑用动态规划求解

  • 先把原问题的规模缩成最小的子问题,确定边界

  • 逐步扩大子问题,并且通过前面步骤的子问题的解来求最新子问题的解

  • 当子问题规模扩大为i时,可推出状态转移方程

例如:原问题dp[i]的解=子问题dp[i-1]的解+子问题dp[i-2]的解

  • dp[i]数组的意义:问题变量的状态。随着i的变化dp[i]记录着问题变量状态的变化过程

二、题解步骤

  1. 确定原问题与子问题
  2. 确认状态,dp[i]数组的意义
  3. 确认边界状态的值
  4. 确认状态转移方程

(理论晦涩难懂,请看下方例题,长文警告!!!)

三、例题

动态规划最经典的问题莫过于背包问题
想要了解的朋友可点击下方的3个传送门
01背包
小破站视频讲解
dalao博客
完全/多重背包
dalao博客

而我更想讲的是下面这题——一道比较简单易懂的dp题

一个机器人位于一个 m x n 网格的左上角,机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

  • 网格中的障碍物和空位置分别用 1 和 0 来表示。
  • m和n的值均不超过100
    来源:力扣(LeetCode)力扣每日一题-20200706

动态规划的题目分为两大类,一种是求最优解类(就是上文所提到的条件反射),典型问题是背包问题,另一种就是计数类,比如这里的统计方案数的问题,它们都存在一定的递推性质。

假设,我们要从左上角的起点a走到右下角的终点b,每次只能向右或者向下移动1格,问:总共有多少条不同路径(暂时不考虑障碍问题)
如下图:
【算法】C++动态规划+滚动数组(面试极其加分的代码)_第1张图片
确定原问题:

首先明确:我们的终极目标就是要到b处(从起点走到终点),这就是我们的原问题,这应该很好理解

确定子问题:

  • 由图和题目可知,我们要走到方格9(b处),那么唯有从方格6或者方格8处直接到达(一次只能向下或者向右移动一步
  • 这个时候我们如果先把问题的范围稍微缩小一下,把终极目标改为走到6处
  • 同理可得,6可由3或者5直接到达,再次缩小范围,依次类推…3只能由2到达,而2只能由1到达…当我们来到这一步的时候,我们的最小子问题就出来了:有多少路径可由1到达2?(也可以理解为从1到达1才是最小子问题)显而易见只有1条,同理,由1到达4也只有1条路径

逐步扩大子问题:

那么如今我们

  • 已知1到2与1到4的路径总和,是不是能求1到5的路径总和了?
  • 已知1到2的路径总和,是不是能求1到3的路径总和了?
  • 已知1到3和1到5的路径总和,是不是能求1到6的路径总和了?

  • 依次类推,我们最终能得到1到6和1到8的路径总和,进而求得我们的终极目标——从a到b处的路径总和

根据我们逐步扩大子问题的过程,我们可以列出下面公式:

cnt[i]:从方格1走到方格i的路径总和

已知1到2与1到4的路径总和,求1到5的路径总和:cnt[5] = cnt[2]+cnt[4];
已知1到2,求1到3的路径总和:cnt[3] = cnt[2];
已知1到3与1到5的路径总和,求1到6的路径总和:cnt[6] = cnt[3]+cnt[5];


已知1到6与1到8的路径总和,求1到9的路径总和:cnt[9] = cnt[6]+cnt[8];

dp[i]的意义:
cnt[i]:从方格1走到方格i的路径总和
此处的 cnt[i] 即我们前文所提到的 dp[i]
从方格1走到方格i的路径总和 即为 dp[i]的意义

我们再把上述公式化为二维进行表示,即:

cnt[1][1] = cnt[0][1

你可能感兴趣的:(面试专栏,算法,动态规划,面试,笔试,微软,百度,腾讯)