# 1. 线性规划基础

可以根据条件列出一个不等式区间,然后根据目标函数来判断极值位于哪里
比如 lec 中的例题

  • 目标函数:最大化形式 f (x,y)=200,000x+250,000yf (x, y) = 200,000x + 250,000yf (x,y)=200,000x+250,000y。

  • 约束条件来自资源限制(如砖块、门、窗):

    • 10,000x+8,000y≤168,000

    • 4x+2y≤60

    • 5x+10y≤150

    • x≥0,y≥0
      示意图:

这个点通过平移 k=-0.8 的线找到的最大交点。

这样类型的情况一般有四种

  1. 单一解,即最大值情况只会在某一个点达到
  2. 无解,比如同时存在 x<1 和 x>2
  3. 解不唯一,比如 f (x,y) 函数与某一个界定条件的边的斜率相同时,整条边都是最优解
  4. 无界,比如 c 向量的方向和界域的开口方向相同

# 2. 增量算法

# 🧩 增量算法的核心思想

我们有很多线性约束(比如 h1,h2,...,hnh_1, h_2, ..., h_nh1​,h2​,...,hn​),它们构成一个凸多边形的可行域。我们希望找到在这个区域中,使目标函数最大的那个点。

而增量算法的思路是:

一条条逐个加入约束,每次更新当前最优解。


# 🪜 增量算法流程(二维情况)

# ✅ 初始化

先人为地加入两个 “大” 的边界(例如 x≤Mx \leq Mx≤M, y≤My \leq My≤M,用于限制区域),形成初始的区域 F0F_0F0​。

  • 通常从一个初始的角点 v0v_0v0​ 开始(比如可行域的右上角)

# ✅ 增量地加入约束

对于第 iii 条约束 hih_ihi​,我们查看:

  1. 如果当前最优点 vi−1v_{i-1} vi−1​ 仍满足新的约束 hih_ihi​
    → 不用更新,直接设 vi=vi−1v_i = v_{i-1} vi​=vi−1​

  2. 如果 vi−1v_{i-1} vi−1​ 不满足 hih_ihi​
    → 新可行区域被切掉了,必须重新计算新的最优点 viv_ivi​,这个点一定在 hih_ihi​ 的边界上

这个操作在二维中很快,因为边界是线段,交点很容易计算。


# 🔁 重复这一过程

直到所有 nnn 个约束都处理完毕,最终的 vnv_nvn​ 就是目标函数的最大值点。


# 📈 时间复杂度

  • 每一步最坏需要重新计算一次最优点,最多耗费 O (i) 时间

  • 总的复杂度是:

    i=1nO(i)=O(n2)\sum_{i=1}^{n} O(i) = O(n^2)


# 🎲 改进版:随机增量算法(Random Incremental Algorithm)

如果我们随机打乱约束的顺序再增量处理,期望复杂度可以降到 O (n)

  • 核心思想是:大多数情况下,新的约束不会改变当前最优解

  • 通过 “后向分析(backward analysis)” 可以证明其期望复杂度为 O (n)

定义随机变量 XiX_iXi​ 表示第 iii 次加约束时,是否需要 “重新计算”:

  • Xi=0 → 如果 vi−1∈hi,不需要更新

  • Xi=1 → 如果 vi−1∉hi​,需要重新找最优解

那么第 iii 步的耗时为:O (i)・Xi

加上初始常数时间,总的运行时间是:

T=n+i=1nO(i)XiT = n + \sum_{i=1}^{n} O(i) \cdot X_i

我们用期望的线性性

E[i=1nO(i)Xi]=i=1nO(i)E[Xi]\mathbb{E}\left[ \sum_{i=1}^{n} O(i) \cdot X_i \right] = \sum_{i=1}^{n} O(i) \cdot \mathbb{E}[X_i]

在随机顺序下,第 iii 步 “需要重新计算” 的概率 \mathbb{E}[X_i] \leq \frac{2}

所以代入总和:

i=1nO(i)2i=i=1nO(1)=O(n)\sum_{i=1}^{n} O(i) \cdot \frac{2}{i} = \sum_{i=1}^{n} O(1) = O(n)

关于这个部分是如何推导出来的,我们可以参考后向分析 (backward analysis)
因为每个 vi 都是两个 hi 的交点,故假设把这两个 hi 放回未分配的 h 集合当中,那么当添加 hi 时会导致最优点为 vi 的概率就为 2/i。

# 🧠 举个例子理解

假设一开始你有一个三角形的可行域,你的目标是找右上角的点(比如利润最大)。如果你突然加入一个 “新约束”—— 在这个三角形上面画一条线往下压,如果原来的最优点还在这条线的下方(满足约束),你啥都不用改;但如果不满足,那你只能重新在新交点里找最大值点

# 3. 最小包围圆问题

给定一个平面上的点集 P={p1,p2,...,pn} P = {p_1, p_2, ..., p_n} P={p1​,p2​,...,pn​},我们要找到:

一个,它包含所有点,且半径最小。

这个圆叫做最小包围圆(Minimum Enclosing Disk, 简称 MED)。


# 🧠 有哪些性质?

  1. 这个圆是唯一的

  2. 最小包围圆的边界上最多有三个点(想想三点确定一个圆)。

  3. 实际上,它的边界上一定有至少两个点,否则可以缩小圆。


# 🚶‍♂️ 我们怎么找到这个圆?

我们可以用一种叫 Welzl’s 随机增量算法,它的思路和线性规划中的随机增量算法非常类似,而且 ** 期望时间复杂度是 O (n)


# 🔁 算法步骤(简化版)

我们记一个辅助函数:
MinDisk(P, R)

  • PPP:还没处理完的点集

  • RRR:已知在圆边界上的点(最多 3 个)

目标是找一个包含所有 PPP 的最小圆,且边界包含所有 RRR 中的点


# ▶ 主函数: MinDisk(P)

  1. 随机打乱点集 PPP

  2. 从前两个点开始构造一个初始圆

  3. 依次加入点 pip_ipi​,检查是否在当前圆 Di−1D_{i-1} Di−1​ 内:

    • ✅ 是:跳过

    • ❌ 否:那么 pip_ipi​ 一定在最小圆边界上 ⇒ 递归调用 MinDiskWith1Pt(P[1..i-1], p_i)


# ▶ 辅助函数: MinDiskWith1Pt(P', p_i)

给定点 pi 一定在圆的边界上:

  1. 对 P′做随机排列

  2. 从 pi​ 和第一个不在圆里的点 pj 开始构造一个新的圆

  3. 如果有点 pk​ 仍在圆外 ⇒ 调用 MinDiskWith2Pts(P[1..j-1], p_i, p_j)


# ▶ 辅助函数: MinDiskWith2Pts(P', p_i, p_j)

这时候我们已经知道 pi​ 和 pj 都必须在圆上:

  1. 找到一个包含 pi,pj 且也包含 P′ 的最小圆

  2. 如果还有点不在圆里,说明它也必须在圆的边界上 ⇒ 用这三个点直接构造外接圆(三点定圆)


# ⏱ 复杂度分析

  • 每个点最多只会触发常数次递归

  • 所以算法的 期望时间复杂度是 O (n)

# 4. 带约束违反的线性规划

# 📌 什么是 “带约束违反” 的线性规划?

标准的线性规划要求所有约束都必须满足:

Maximize f(x)=cTxsubject to Ax≤b\textMaximize } f(x) = c(T x \quad \text{subject to)Ax \leq bMaximize f(x)=cTxsubject to Ax≤b

但是现实中很多问题可能:

  • 有一些约束 很严格,稍微放松一点效果可能更好

  • 或者数据本身就有误差、冲突,无解

所以我们允许最多违反 kkk 条约束,这样就变成了:

找一个解,使目标函数最大,同时最多违反 kkk 个约束。

这类问题称为:

Linear Programming with Violations\textbf{Linear Programming with Violations}Linear Programming with Violations


# 🧠 举个例子帮助理解:

你是工厂老板,有 10 条资源限制(约束),但你愿意 “睁一只眼闭一只眼”,允许最多放宽 2 条,这样可能整体利润更高。


# 📏 问题形式化(from 讲义)

  • 原始线性规划有 n 条约束(不等式)

  • 我们现在允许最多扔掉 k 条约束

  • 目标是:找到一个满足其余 n−k 条约束的最优解


# ❗问题难点:

你可以想象,暴力枚举 “扔掉哪 kkk 条” 要试很多种:

  • 总共有 (nk)=O(nk)\binom{n}{k} = O(n^k) 种组合

  • 每种组合要解一次线性规划(假设可以在线性时间里解决)

  • 那么总时间就是:

    O(nk+1)O(n^{k+1})

太慢了!


# ✅ 怎么办?引入随机化算法

讲义里介绍了一种非常聪明的方法:


# 🎲 随机算法流程(核心思想):

  1. 重复执行 M 次,每次:

    • 以概率 1k\frac{1}{k} 从原始约束中随机挑出一个子集 L′

    • 解这个子集构成的线性规划

    • 如果这个解只违反了最多 k 条原约束,就记录它

  2. 最后取这些尝试中 “最好” 的解作为结果


# ✅ 算法优势:

虽然一次尝试成功的概率不高,但我们可以多试几次 —— 就像买彩票,买得够多,总能中大奖。

通过分析可知,只要我们重复:

M=O(kdlog(1/δ))M = O(kd \cdot \log(1/\delta))

次尝试,就能以至少 1δ1 - \delta 的概率找到最优解。


# 📈 最终复杂度:

O(nkdlog(1/δ))O(nkd \cdot \log(1/\delta))

比暴力 O(nk+1)O(n^{k+1}) 快很多!


# 🔚 总结一句话:

“带约束违反” 的线性规划,就是允许你最多扔掉 kkk 条限制来找最优解。虽然暴力方法慢,但可以通过随机算法在线性时间内高概率找到最优解,特别适合约束很多、但你只想放松一小部分的场景。