文章目录

区间型动态规划有点像坐标型,因为i和j就是表示第i个到第j个。
667 · 最长的回文序列
动态规划4步法:
1、确定状态
最后一步
子问题
2、转移方程
3、初始条件和边界情况
注意区间型动态规划的初始条件不再是f[0][0],f[0][1]…f[0][n-1]。而是f[0][0], f[1][1]…f[n-1][n-1]。
4、计算顺序
计算循序和之前也不同,也是区间型动态规划最难的部分。不能按照i的顺序去算了。
老师写的代码:
下面是我按照老师的思路,写的代码:
一定要注意老师讲的计算顺序问题。以及i的取值,j的计算。
def longest_palindrome_subseq(self, s: str) -> int:
# write your code here
if not s or len(s) == 0:
return 0
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = 1
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = 2
else:
dp[i][i + 1] = 1
# len 3 --> n
for length in range(3, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
if s[i] == s[j]:
dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + 2)
return dp[0][n - 1]
记忆化搜索
递归不能用滚动数组。
老师的记忆化搜索代码:
递归的终止条件就是递推的初始条件。
396 · 硬币排成线 III
Sx = -Sy + m,对于当前的X来说,它要做的就是让对手y最优取负数,加上这轮X取的一个数m。
动态规划4步法:
1、确定状态
最后一步
子问题
2、转移方程
注意最后f[i][j+1]那里老师写错了,应该是f[i][j - 1]
3、初始条件和边界情况
这里同样写错了
注意f[i][j+1]那里老师写错了,应该是f[i][j - 1]
4、计算顺序
老师写的代码:
现在根据老师的思路,可以写出来了,但是夏天老师说,到后期,写代码是简单的,想出来才是最难的。还是要多做题才可以。
def first_will_win(self, A: List[int]) -> bool:
# write your code here
if not A or len(A) == 0:
return True
n = len(A)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = A[i]
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = max(A[i] - dp[i + 1][j], A[j] - dp[i][j - 1])
return dp[0][n - 1] >= 0
430 · 攀爬字符串
动态规划4步法:
1、确定状态
最后一步
子问题
2、转移方程
情况二,s1和t2长度都是w,s2和t1都是k-w。
3、初始条件和边界情况
4、计算顺序
老师的代码
这题太难了,不写了。
168 · 吹气球
消去型不用顺着题目去想,还是回到最后一步。只剩一个气球。那么它的子问题就是左边的区间,和右边的区间。并且这两个区间是互不影响的。
动态规划4步法:
1、确定状态
最后一步
子问题
2、转移方程
3、初始条件和边界情况
4、计算顺序
老师的代码:
优化:
def max_coins(self, B: List[int]) -> int:
# write your code here
if not B or len(B) == 0:
return 0
A = [1] + B + [1]
n = len(B)
dp = [[0] * (n + 2) for _ in range(n + 2)]
for i in range(n + 1):
dp[i][i + 1] = 0
for length in range(3, n + 3):
for i in range(n + 2):
j = i + length - 1
if j > n + 1:
break
for k in range(i + 1, j):
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + A[i] * A[k] * A[j])
return dp[0][n + 1]