Dynamic problem动态规划

本文详细介绍了动态规划的概念,通过实例探讨了最大连续子列和、最长不下降子序列、最长公共子序列(LCS)、最长回文连续子串以及背包问题(01背包和完全背包)的解决方案,包括状态转移方程和优化技巧。同时,提供了相关算法题目的讲解链接,是学习动态规划的好资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考算法笔记

1.什么是动态规划

2.最大连续子列和

计算一个序列A[]
状态转移方程
dp[i]=max{A[i], dp[i-1]+A[i]}

3.最长不下降子序列

LIS: Longest Increasing Sequence

问题:在一个数字序列中,找一个最长的子序列(可以不连续),
使得这个子序列是非下降的。

方案一

对于每个元素都有选和不选,时间复杂度是 O ( 2 n ) O(2^n) O(2n)

方案二

状态转移方程:
dp[i]=max{1, dp[j]+1}
(j=0,1,…,i-1 && A[j]<=A[i])
例题:PAT A1045,讲解

4.最长公共子序列(LCS)

Longest Commom Subsequence, LCS
暴力方法:
对两个字符串m, n,每个字符都有选和不选,然后在比较,总时间复杂度为 O ( 2 m + n ∗ m a x ( m , n ) ) O(2^{m+n} * max(m, n)) O(2m+nmax(m,n))

dp方法:
dp[ i ][ j ]代表字符A的i号位和字符B的j号位之前的LCS。
d p [ i ] [ j ] = { d p [ i − 1 ] [ j − 1 ] + 1 , A [ i ] = B [ i ] m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) , A [ i ] ! = B [ i ] dp[i][j]=\left\{ \begin{aligned} dp[i-1][j-1]+1, A[i] = B[i] \\ max(dp[i-1][j], dp[i][j-1]), A[i] != B[i] \end{aligned} \right. dp[i][j]={dp[i1][j1]+1,A[i]=B[i]max(dp[i1][j],dp[i][j1]),A[i]!=B[i]
边界: d p [ i ] [ 0 ] = d p [ 0 ] [ j ] , ( 0 &lt; = i &lt; = n , 0 &lt; = j &lt; = m ) dp[i][0]=dp[0][j], (0&lt;=i&lt;=n, 0&lt;=j&lt;=m) dp[i][0]=dp[0][j],(0<=i<=n,0<=j<=m)
时间复杂度O(m*n)。

5.最长回文连续子串

对于一个字符串S

  1. 暴力枚举:枚举子串两个端点[i, j], 然后判断回文,时间复杂度 O ( n 2 ∗ n ) O(n^2*n) O(n2n)
  2. 令dp[i][j]表示S[i]至S[j]的子串是否为回文串,则有状态转移方程:

d p [ i ] [ j ] = { d p [ i + 1 ] [ j − 1 ] + 1 , S [ i ] = = S [ i ] 0 , S [ i ] ! = S [ i ] dp[i][j]=\left\{ \begin{aligned} &amp; dp[i+1][j-1]+1&amp;, S[i] == S[i] \\ &amp; 0 &amp;, S[i] != S[i] \end{aligned} \right. dp[i][j]={dp[i+1][j1]+10,S[i]==S[i],S[i]!=S[i]
时间复杂度 O ( n 3 ) O(n^3) O(n3)
应该考虑按照子串的初始长度进行枚举(从3到n/2)。

6.背包问题

6.1 01背包问题

有n件物品,每件物品的重量为w[i], 价值为c[i]。现在有一个容量为V的背包,使得背包内物品总价值最大,且每件物品只有一件。

令dp[i][v]表示前i件物品恰好装入容量v的背包里获得的价值。 ( 0 ≤ i ≤ n , 0 ≤ v ≤ V ) (0\le i \le n ,0 \le v \le V) (0in,0vV)

  1. 若不放第i件物品,则总价值等于前i-1的物品放入容量v的背包,即dp[i-1][v]。
  2. 若放第i件物品,则总价值是前i-1的物品放入容量v-w[i]的背包, 加上c[i],即dp[i-1][v-w[i]]+c[i]。

所以: d p [ i ] [ v ] = m a x ( d p [ i − 1 ] [ v ] , d p [ i − 1 ] [ v − w [ i ] ] + c [ i ] ) dp[i][v]=max(dp[i-1][v], dp[i-1][v-w[i]]+c[i]) dp[i][v]=max(dp[i1][v],dp[i1][vw[i]]+c[i])
边界条件:dp[0][v]=0。 0<=v<=V。

时间复杂度O(n*V),空间复杂度也是的。
可以使用滚动数组进行空间复杂度的优化,但是v从V到w[i](逆序!)。
例题:https://blog.youkuaiyun.com/qq_44761480/article/details/99827377

6.2 完全背包问题

有n件物品,每件物品的重量为w[i], 价值为c[i]。现在有一个容量为V的背包,使得背包内物品总价值最大,每件物品有无数件。

令dp[i][v]表示前i件物品恰好装入容量v的背包里获得的价值。 ( 0 ≤ i ≤ n , 0 ≤ v ≤ V ) (0\le i \le n ,0 \le v \le V) (0in,0vV)

  1. 若不放第i件物品,则总价值等于前i-1的物品放入容量v的背包,即dp[i-1][v]。
    2. 若放第i件物品,则总价值是前i的物品放入容量v-w[i]的背包, 加上c[i],即dp[i][v-w[i]]+c[i]。注意这里i并不是放了多少件,而是前i件物品。

    所以:状态转移方程 d p [ i ] [ v ] = m a x ( d p [ i − 1 ] [ v ] , d p [ i ] [ v − w [ i ] ] + c [ i ] ) dp[i][v]=max(dp[i-1][v], dp[i][v-w[i]]+c[i]) dp[i][v]=max(dp[i1][v],dp[i][vw[i]]+c[i])
    边界条件: d p [ 0 ] [ v ] = 0 。 0 &lt; = v &lt; = V dp[0][v]=0。 0&lt;=v&lt;=V dp[0][v]=00<=v<=V

改成一维形式:
d p [ v ] = m a x ( d p [ v ] , d p [ v − w [ i ] ] + c [ i ] ) dp[v]=max(dp[v], dp[v-w[i]]+c[i]) dp[v]=max(dp[v],dp[vw[i]]+c[i])
注意:v的枚举顺序是正向枚举。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值