时间:2024-11-17 20:46
人气:
作者:admin
动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 -----OI Wiki
DP四步
定义\(dp_i\)表示以\(i\)结尾的最大子段和
答案即\({\max}^{i\in[1,n]}_{dp_i}\)
对于每个\(i\):
求\(\max\)
即\(dp_1\)为\(a_1\)
定义\(f(i)\)为以\(i\)结尾的最大子段和
则递归分析即可
int f(int x){
if(x==1){//边界条件
return a[1];
}
return max(f(x-1)+a[x],a[x]);//求最大值
、}
这样时间很慢,原因是存在许多已经算过的节点被重复计算
所以用一个\(val\)记录计算过的节点信息
for(int i=1;i<=n;i++){
dp[i]=inf;
}
int f(int x){
if(dp[x]!=inf){
return dp[x];//已经记录过的节点信息
}
if(x==1){//边界条件
return a[1];
}
dp[x]=max(f(x-1)+a[x],a[x]);//求最大值
return dp[x];
}
上述优化方法即记忆化搜索,是一种基本DP方法
记忆化搜索是一种通过记录已经遍历过的状态的信息,从而避免对同一状态重复遍历的搜索实现方式。 ------OI Wiki
转成递推形式就成了基本的线性DP
dp[1]=a[1];
for(int i=2;i<=n;i++){
dp[i]=max(dp[i-1]+a[i],a[i]);
maxi=max(maxi,dp[i]);
}
DP四步
定义\(dp_i\)表示以\(i\)结尾的最长上升子序列长度
答案即\({\max}^{i\in[1,n]}_{dp_i}\)
对于每个\(i\),有若干\(j<i\)且\(a_j<a_i\):
求\(\max\)
即\(dp_i\)为\(1\),因为每个\(dp\)值至少为\(1\)
使用递推,枚举\(i\),并且枚举\(j(j<i)\)
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(a[j]<a[i]){
dp[i]=max(dp[j]+1,dp[i]);
}
}
maxi=max(maxi,dp[i]);
}
第一小问即求最长不上升子序列长度
第二问可以用Dilworth 定理解决
把序列分成不上升子序列的最少个数,等于序列的最长上升子序列长度。把序列分成不降子序列的最少个数,等于序列的最长下降子序列长度。
所以第二问等价于求最长上升子序列长度
使用贪心优化如果,如果一个位置可以有\(2,3\)两个数选一个数,我们一定会选\(2\),因为选2后面就有更多的机会拼接。
定义一个\(c\)数组存贮已经选了的数
只要每次二分查找第一个能够等价替换的数,就能将其替换,在过程中记录DP即可。
DP的要素:
本人(KK_SpongeBob)蒟蒻,写不出好文章,但转载请注明原文链接:https://www.cnblogs.com/OIer-QAQ/p/18551071/study_DP
上一篇:FPGA时序约束基础
下一篇:DSB的数字正交解调