动态规划-最大子段和其变式
最大子段和
给出一个长度为 \(n\) 的序列 \(a\),选出其中连续且非空的一段使得这段和最大。
\(O(n^3)\) :枚举左右端点,再进行 \(O(n)\) 求和。
\(O(n^2)\) :同上,求和使用前缀和优化 \(O(1)\) 查询。
\(O(n)\) : DP写法//
模拟求最大子段和的过程,从左到右顺序遍历,从第一个数开始考虑,考虑到第1个数时,此时以1为结尾最大子段和为a[1]。考虑第二个数如果a[1]+a[2]>a[2],此时以2为结尾的最大子段和是a[1]+a[2],如果a[1]+a[2]<a[2],此时以2为结尾的最大子段和是a[2]。
状态:所以我们可以顺序遍历,考虑以i为结尾的子段,是自己自创门派还是和邻居一起会获得更优的结果。因此我们可以设计状态为 f[i]为结尾,获得的最大连续子段和。
转移:
- a[i]+f[i-1]>a[i] 和邻居合伙的收益更大。$ f[i]=a[i]+f[i-1]$
- a[i]+f[i-1]<a[i] 自创门派的收益更大 $ f[i]=a[i]$
- a[i]+f[i-1]=a[i] 收益好像一样,那该怎么?其实加不加上没影响。如果加上的话就可以。连接两段,使你的最大子段和更长。
长度等于、大于、小于k的最大子段和
暴力算法同上
等于:\(O(n)\) 单调队列,顺序遍历,求出 i-m+1 到 i 子段和,维护最大子段和。
大于:\(O(n*m)\) 单调队列,顺序遍历,枚举\(k(k<i-m+1)\)求出 k 到 i子段和,维护最大子段和。
小于:\(O(n*m)\) 单调队列,顺序遍历,枚举\(k(i-m+1<k<=i)\)求出 i 到 k子段和,维护最大子段和。
环状最大子段和
处理环型的问题都有一个通用的解法 将数据复制一份在末尾,环的问题就变成的普通的链的问题。
最大两端子段和
\(O(n)\) 考虑枚举两端和中间的空点,只需要求出 空点左侧的子段最大和和空点右侧的子段最大和,再维护两端最大和即可。空点左右侧的最大和,可以通过预处理的得到。
参考文献
本文来自博客园,作者:Wh1sky,转载请注明原文链接:https://www.cnblogs.com/wh1sky/p/18003388

浙公网安备 33010602011771号