Martian148's blog Martian148's blog
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档

Martian148

一只热爱文科的理科生
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档
  • 线上赛板子(实时更新)
  • 数据结构

  • 数学

  • 计算几何

  • 动态规划

    • 背包问题
    • DP优化
      • 单调队列优化 DP
      • 四边形不等式优化 DP
    • SOSDP
  • 图论

  • 字符串

  • 杂项

  • 算法笔记
  • 动态规划
martian148
2024-08-29
目录

DP优化

# DP 优化

# 单调队列优化 DP

单调队列在 DP 中优化的基本应用,是对这样一类 DP 状态转移方程进行优化

dp[i]=min⁡{dp[j]+a[i]+a[j]},L(i)≤j≤R(i) dp[i] = \min\{dp[j] +a[i]+a[j]\},L(i) \le j \le R(i) dp[i]=min{dp[j]+a[i]+a[j]},L(i)≤j≤R(i)

方程的特点是其中关于 iii 的项 a[i]a[i]a[i] 和关于 jjj 的项 a[j]a[j]a[j] 是独立的。 jjj 被限制在窗口 [L(i),R(i)][L(i),R(i)][L(i),R(i)] 内

如果单纯的枚举 jjj ,复杂度为 O(n2)O(n^2)O(n2) 但是使用单调队列优化可以到 O(n)O(n)O(n)

我们假设 jjj 的活动窗口为 i−k≤j≤ii-k \le j \le ii−k≤j≤i ,那么发现 iii 和 i+1i+1i+1 所对应的 jjj 有很大一部分重叠,产生了重复计算,如果我们能减少这些重复计算就能优化复杂度

image.png

在 iii 增大的过程中,我们用一个单调队列来维护决策 dp[j]+a[j]dp[j]+a[j]dp[j]+a[j] 的最小值,因为对于 iii 来说 a[i]a[i]a[i] 可以看成是常量

考虑维护 dp[j]+a[j]dp[j]+a[j]dp[j]+a[j] 的最小值,如果一个 jjj 比 j′j'j′ 更靠右并且 dp[j]+a[j]<dp[j′]+a[j′]dp[j]+a[j] < dp[j']+a[j']dp[j]+a[j]<dp[j′]+a[j′] 那么 j′j'j′ 就没有存在的意义了,因为 jjj 能往后拓展的 iii 要比 j′j'j′ 多

那么如何取得答案?如果这是一个单调递增的队列,那就取头,如果头部的节点不合法,在 jjj 的窗口外,那就再取一个,直到合法为止

# 四边形不等式优化 DP

一些常用的区间 DP 问题的状态转移方程为:

dp[i][j]=min⁡k=ij−1{dp[i][k]+dp[k+1][j]+w[i][j]} dp[i][j]=\min_{k=i}^{j-1}\{dp[i][k]+dp[k+1][j]+w[i][j]\} dp[i][j]=k=iminj−1​{dp[i][k]+dp[k+1][j]+w[i][j]}

w[i][j]w[i][j]w[i][j] 满足以下几个性质时:

image.png
  1. 四边形不等式:设 a≤b≤c≤da\le b\le c\le da≤b≤c≤d 有, w[a,d]+w[b,c]≥w[a,c]+w[b,d]w[a,d]+w[b,c]\ge w[a,c]+w[b,d]w[a,d]+w[b,c]≥w[a,c]+w[b,d],包含和 ≥\ge≥ 交叉和
  2. 单调性:设 i≤i′≤j′≤ji \le i' \le j' \le ji≤i′≤j′≤j 满足:w[i][j]≤w[i′][j′]w[i][j] \le w[i'][j']w[i][j]≤w[i′][j′]

DP 转移的最后一层 kkk 可以减小范围

for (int len = 1; len <= n; len ++)
	for (int i = 1; i + len - 1 <= n; i ++){
		int j = i + len - 1;
		for (int k = p[i][j-1]; k <= p[i + 1][j]; k ++){
			if(dp[i][j] > dp[i][k] + dp[k + 1][j] + w[i][j]){
				dp[i][j] = dp[i][k] + dp[k + 1][j] + w[i][j];
				p[i][j] = k;
			}
		}
	}
1
2
3
4
5
6
7
8
9
10

其中 p[i][j]p[i][j]p[i][j] 表示 dp[i][j]dp[i][j]dp[i][j] 的决策点

上次更新: 2025/04/08, 18:03:31
背包问题
SOSDP

← 背包问题 SOSDP→

最近更新
01
Java基础语法
05-26
02
开发环境配置
05-26
03
pink 老师 JavaScript 学习笔记
05-26
更多文章>
Theme by Vdoing | Copyright © 2024-2025 Martian148 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式