动态规划笔记 dynammic programming notes
Table of contents
<h2 id="def_dp">动态规划 Dynamic Programming</h2>
动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。
通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
动态规划问题的本质:求最值
-
原问题 <=> 若干个类似的独立子问题
- 状态转移方程
解决动态规划问题的一般流程
-
确定
state
即区分原问题和子问题的量,一般为
dp function
的自变量或dp array
的index
e.g 原问题为dp(n), 子问题为dp(n-1) -
确定
base state case
一般为state=0的情况, 即
dp(0)
或dp[0]
-
确定
strategy
即原问题分解成子问题*的不同方法
e.g.
-
定义
dp function
或dp array
(状态转移方程)根据strategy列出方程
-
自顶向下: dp function
- 可能会重复计算某些子问题 => 用hash table储存已经计算了的子问题
- 时间复杂度,空间复杂度都很高
-
-
自底向上
#原问题的状态 state_original_problem = 11 #dp数组 dp = [some big value] * (state_original_problem+1) #base state dp[0] = dp[1] = 0 #自底向上 for i in range (2,len(dp)): dp[i] = min(dp[i-1]+2,dp[i-2]+1) #返回结果 return dp[-1]
Time complexity O(n), space complexity O(n)
-
Optimisation: 若dp[n]只与dp[n-1], dp[n-2]有关,则可以用滚动数组的思想优化
dp_i = 0 #dp[n-2] dp_j = 0 #dp[n-1] for i in range(2,n+1): dp_n = min(dp_i+1,dp_j+2) dp_i = dp_j dp_j = dp_n return dp_j
Space complexity: O(1)
Reference:
Examples
<a href="https://leetcode-cn.com/problems/maximal-rectangle/" id = "exa1">85. Maximal Rectangle</a>
Given a rows
x cols
binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.
Example 1:
Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
Output: 6
Explanation: The maximal rectangle is shown in the above picture.
动态规划思想:
heights[i][j]代表[i,j]的高度 heights[i][j] = matrix[i][j]=='1'? heights[i-1][j] + 1:0 dp[i][j][k] 代表以[i,j]为右下角,高度为k可以组成的最大面积 dp[i][j][k] = matrix[i][j]=='1'? dp[i][j-1][k] + k : 0
代码:
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int n = matrix.size();
int m = 0;
if (n > 0) { m = matrix[0].size(); }
vector<vector<int>> heights(n + 1,vector<int>(m + 1,0));
vector<vector<vector<int>>> dp(n + 1,vector<vector<int>>(m + 1, vector<int>(n + 1, 0)));
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (matrix[i-1][j-1] == '0') { continue; }
heights[i][j] = heights[i-1][j] + 1;
for (int k = 1; k <= heights[i][j]; k++) {
dp[i][j][k] = dp[i][j-1][k] + k;
ans = max(ans, dp[i][j][k]);
}
}
}
return ans;
}
};