动态规划
动态规划
好吧,其实算是复习的。
动态规划(Dynamic Programming,简称DP),是指一种解决特定问题的一种方法。其通过将一个大问题拆分成多个较为简单的小问题,大问题的最优解由小问题的最优解合并而来的方式动态的解决问题。
首先,有几个概念需要阐述:
- 阶段:将所给问题的求解过程恰当的分成多个相互联系的阶段,以便于求解,即拆分而来的多个子问题。
- 状态:表示每个阶段开始时进行转移到下一个状态所需的条件,通常,一个阶段具有多个状态。
- 决策:当处于某一阶段的某一状态时,可以做出不同的决定,从而确定下一阶段的状态,这种决定称为决策,描述决策的变量称为决策变量。
- 状态转移方程:在 \(DP\) 中本阶段的状态通常由上一阶段的状态和决策转移而来,由第 \(i\) 步的状态 \(f(i)\) ,和决策 \(u(i)\) 来确定第 \(i+1\) 段的状态。表示为 \(F(i+1)=T(f(i),u(i))\) ,这称为状态转移方程。
其次,要解决的问题必须符合两个性质才可以使用动态规划
- 无后效性:本阶段之前做出的决策不会影响之后的决策进行
- 最优子结构:即本阶段的最优解也是全局最优解,也就是全局最优解由局部最优解合并而来。
例题:
1.硬币问题:
题目描述:今有面值为 1、5、11 元的硬币各无限枚。想要凑出 \(n\) 元,问需要的最少硬币数量。
由于币值并不太完美,导致贪心的做法会被 \(hack\) 掉,考虑使用 \(DP\) 的方式,设 \(dp[i]\) 表示凑 \(i\) 元钱所需的最少钱币数,则其可以由其之前的三种状态转移而来,即 \(dp[i-1],dp[i-5],dp[i-11]\) 三种状态转移而来,则其的状态转移方程为
\(O(n)\) 的复杂度即可解决问题,非常好复杂度,这使时限旋转。
2.序列问题
(1.)最大子段和问题:
题目描述:给出一个长度为 \(n\) 的序列 \(a\) ,选出其中连续且非空的一段使得这段和最大。
设 \(dp[i]\) 表示以 \(i\) 结尾的最大子序列和,则其由上一最大子序列和转移而来或其自己为最大子段和。可推出其状态转移方程为
\(O(n)\) 扫一遍即可。
(2.)最长连续上升子序列(LIS):
题目描述:给出一个长度为 \(n\) 的序列 \(a\) ,选出其中连续且非空的一段使这一段上具有 \(a_i<a_j(i<j)\) 。
设 \(dp[i]\) 表示以 \(i\) 结尾的最长连续上升子序列。考虑如何进行状态转移,如果 \(a[i]>a[i-1]\) 则有 \(dp[i]=dp[i-1]+1\) ,此时考虑边界问题,由于最长上升子序列最短为一,则初始化时 \(dp[i]=1\) 。则得出状态转移方程:
同样是 \(O(n)\) 的复杂度。
(3.)最长公共子序列(LCS):
题目描述:给予两个字符串 \(s1,s2(s1=x_1,s_2,x_3...x_m|s2=z_1,z_2,z_3...z_k)\) ,存在一个严格递减的下标序列 \(<i_1,i_2,i_3,...,i_k>\) 使得对于所有 \(j=1,2,3...k\) 有:\(s1_{[i,j]}=s2_j\) 。
设 \(dp[i][j]\) 为 \(s1\) 第 \(i\) 位到 \(s2\) 第 \(j\) 的最长公共子序列,若有 \(s1_i=s2_j\) 则有 \(dp[i][j]=dp[i-1][j-1]+1\) ,若无,则有 \(dp[i][j]=max(dp[i-1][j],dp[i][j-1])\) ,得出状态转移方程:
3.背包问题:
(1.)01背包问题:
题目描述:一个旅行者有一个最多能装 \(M\) 公斤的背包,现在有 \(n\) 件物品,它们的重量分别是 \(W_1,W_2...W_n\) 它们的价值分别为 \(C_1,C_2...C_n\) ,求旅行者能获得最大总价值。
对于每一个物品,有两种状态(取或不取),其实这也就得出了状态转移方程
(2.)完全背包问题
题目描述:设有 \(n\) 种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为 \(M\) ,今从 \(n\) 种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于 \(M\) ,而价值的和为最大。
其实是01背包问题的一种子问题,即讨论每个物品取几个,多一层循环讨论取几个即可。
ok,先写到这,剩下以后再写,润了。