【随笔杂谈】课堂笔记记录 - 归约、问题类和常见困难问题
通过解决一个问题去解决定义公文题的算法将叫做归约,假设其中一个是 \(A\),另一个是 \(B\),如果问题 \(B\) 也可以规约到问题 \(A\) 上,那么 \(B\) 比 \(A\) 难。
归约有几种不同的细分形式,我们设 \(f\) 是任意一个解决问题 \(A\) 的算法,如果存在一个可计算函数可以把问题 \(B\) 的输入转化成 \(A\) 的输入,只调用一次 \(f\) 并且直接输出 \(f\) 的结果,称为映射归约。如果我们可以把 \(f\) 当成一个指令在算法中多次使用并且任意处理它的输入输出,称为 Turing 归约。如果这个算法调用多项式次 \(f\) 且其他部分的时间是多项式的,称为 Cook 归约
对于一个 NP 问题(存在一个多项式时间的验证算法使得问题的一个输入有解当且仅当存在一个多项式长度的证据或者说合法方案 \(u\) 能被验证),如果一个问题能让所有 NP 问题规约到其,我们称这个为 NP-hard 问题。
对于一个 NP-hard 问题,本身还是 NP 问题,我们称这个问题是 NP 完全问题(NPC 问题)。
常见的 NP 难问题
- SAT:给定一个由变量和“与或非”、括号组成的逻辑表达式,问是否存在一种给每个变量分别赋值 True/False 的方式使得整个式子为 True。
- 3-SAT:给定一个由变量和“与或非”、括号组成的逻辑表达式,保证表达式形式是:$(X ∨ X ∨ X) ∧ (X ∨ X ∨ X) ∧ (X ∨ X ∨ X) ∧ · · · $。其中每个 X 都是一个常量 True/False,一个变量或者一个变量取非的结果。一个括号内的表达式称为一个子句。问是否存在一种给每个变量分别赋值 True/False 的方式使得整个式子为 True。
- MAX 2-SAT:给定若干个由变量和“与或非”、括号组成的逻辑表达式子句,保证每个子句形式是:\((X ∨ X)\)。其中每个 X 都是一个常量(True/False),一个变量或者一个变量取非的结果。问给每个变量赋值,最多能让多少个子句求值为 True。
- 判断一个数集是否有子集和为特定值
NP 等问题类度量输入规模看的是输入长度,也就是允许高精度的重量和权值。所以 \(O(V)\) 不是多项式的。
背包系问题大都有限制重量和权值范围的伪多项式算法。
伪多项式算法:时间复杂度为输入的数的数值范围的多项式的算法,比如背包 dp 的 \(O(mn)\) 就是伪多项式算法。
拥有伪多项式算法的 NP 完全问题被称为弱 NP 完全问题,比如背包问题。
常见强 NP 完全问题
- 装箱问题:\(n\) 个物品装入 \(m\) 个背包,每个背包的大小都为 \(M\),问能否装下。
- 多机调度问题:n 个物品装入 m 个背包,最小化最大的背包重量
- 最优化版装箱问题:n 个物品装入若干大小为 M 的背包,问最少要几个背包。
- 三元组均分问题:给定 \(3n\) 个 \([1, M]\) 的整数,问能否分成 \(n\) 组,每组恰好 \(3\) 个,使得每组的和相等。
多项式算法的强度:强多项式算法是指复杂度和输入数值无关的算法(假设计算模型可以执行无限精度计算),弱多项式时间算法可以与数值范围的位数是多项式,比如二分答案是弱多项式时间算法。

浙公网安备 33010602011771号