常用算法设计和优化策略

下面是紫书上讲的常用算法设计策略和优化策略:

  • 分治法:将问题分成相同的独立子问题求解。在普通的分治之外,还有一种cdq分治(陈丹琦分治),思想是处理左边区间到右边区间的影响,归并算一个例子。
  • 动态规划
  • 第一种用法 本质是:对于一个问题,通过定义状态来分解问题。利用状态之间的联系(转移方程)进行递推,最终解决问题。这种用法中,状态的值就构成了最终答案。
  • 第二种用法 本质是:一个问题的答案由许多子问题得到。我们剥离出影响这些子问题答案的元素,将它考虑在dp状态中。这样,一个dp状态就可以表示若干个子问题,考虑某个dp状态就相当于考虑若干个子问题。这种用法中,状态只是用来把类型相同的子问题归为一类。

拆分出的状态必须满足最优子结构性质和无后效性(当前阶段以前的状态不会影响以后的状态,只与当前阶段有关)。动归的目的是避免重叠子问题。递推和递归(记忆化搜索)是实现动归的手段。

只要满足:1.状态设计不重不漏 2.转移方程正确 3.能顺利统计答案,那么这个dp就是可写的。如果在码代码的时候, 初始状态的值设置对了,同时考虑了边界情况,那么这个dp代码就是正确的。

决策单调性:第i个阶段,如果从j转移,那么i以后的阶段,都不会从j及以前的阶段转移。

做题的时候可以考虑先写出原始的转移方程,再用各种方法优化,如将一些一环扣一环的转移压缩成一个转移/利用前缀和思想/利用单调队列或者优先队列/利用线段树……

  • 贪心法:动态规划的一种,每个阶段的最优解是由上一个阶段的最优解得到的。贪心的情况下,局部最优解构成了全局最优解。在找出动态规划的方法以后可以尝试贪心解法。
  • 收缩法:对于某些问题,可以用反证法证明答案只会收缩到某些边界处,判断边界情况即可。
  • 构造法:最朴素的方法。包括模拟,暴力,暴搜……
  • 等价转换:化繁为简,包括问题转换,问题分解等。例如最值反演。
  • 假设法:对于有对称性的问题,利用对称性避免讨论。
  • 使用数据结构:在不改变主算法的情况下加速算法。包括但不限于并查集,单调X,平衡树,线段树,lct……
  • 数形结合:将代数的关系转化成几何的关系。
  • 二分答案:将求某个最优值问题转化为判定性问题,也算在策略内。它的衍生算法还有整体二分,即把询问和答案一起二分。
  • 扫描法:带有顺序的枚举法,通常维护一些重要的量从而简化计算。
  • 枚举基准:寻找基于当前基准的最优值,再取所有基准的最值。某些看似状压的题可以用这种方法,在外层枚举基准状态,然后神奇解决……