不再要求总是找到最优解,在实际应用中有时很难确定一个最优解和近似最优解之间的差别,因问题的输入实例数据本身就可能是近似的。设计一个算法能够求出所有情况下的次优解来解NP-hard问题往往是有效的手段。
近似比定义为算法求得的近似解的目标函数值与最优解的目标函数值之间的比值。
一个优化问题 Π \Pi Π由三部分构成:
对于一个优化问题 Π \Pi Π和它的任一实例 I I I, o p t ( I ) opt(I) opt(I)表示相应实例 I I I的最优解的目标函数值,而 A ( I ) A(I) A(I)表示给定实例 I I I算法 A A A求出的近似解的目标函数值。
近似算法 A A A的近似比形式化定义为:
最小值问题求解的近似比定义: r ( A ) = s u p I A ( I ) o p t ( I ) r(A)=sup_I{{A(I)}\over{opt(I)}} r(A)=supIopt(I)A(I)
最大值问题求解的近似比定义: r ( A ) = s u p I o p t ( I ) A ( I ) r(A)=sup_I{{opt(I)}\over{A(I)}} r(A)=supIA(I)opt(I)
给定n种物品和一个背包。物品 i i i的重量是 w i w_i wi,其价值为 v i v_i vi,背包的容量是 S S S。应该如何装入背包的物品,使得装入背包中物品的总价值最大?
DP求解:
递归式的形式为:
m ( i , j ) = max { m ( i + 1 , j ) , m ( i + 1 , j − w i ) + v i } , j ≥ w i m(i, j)=\max\{m(i+1,j), m(i+1,j-w_i)+v_i\},j\geq{w_i} m(i,j)=max{m(i+1,j),m(i+1,j−wi)+vi},j≥wi
m ( i , j ) = m ( i + 1 , j ) , 0 ≤ j ≤ w i m(i, j)=m(i+1,j), 0\leq{j}\leq{w_i} m(i,j)=m(i+1,j),0≤j≤wi
DP求解的算法复杂度分析:
从 m ( i , j ) m(i,j) m(i,j)的递归式容易看出,算法需要 O ( n ⋅ S ) O(n\cdot{S}) O(n⋅S)的计算时间,其中S表示背包容量,这是一个伪多项式时间算法,因为当 S > 2 n S\gt{2^n} S>2n时,算法需要 Ω ( n ⋅ 2 n ) \Omega(n\cdot{2^n}) Ω(n⋅2n)的计算时间。
对于0-1背包问题,当问题的输入变得无穷大时,我们需要付出极大的代价才能得到问题的最优解。对此我们希望设计一个**近似算法(2-近似算法)**能够保证该问题在多项式时间内被解决。
输入: 正整数 S , w 1 , v 1 , w 2 , v 2 , . . . , w n , v n S, w_1, v_1, w_2, v_2, ..., w_n, v_n S,w1,v1,w2,v2,...,wn,vn。
首先,1)依据 v i w i {{v_i}\over{w_i}} wivi(物品 i i i的价值与重量之比)对物品进行排序,不妨设 v 1 w 1 ≥ v 2 w 2 ≥ . . . ≥ v n w n {{v_1}\over{w_1}}\geq{{v_2}\over{w_2}}\geq...\geq{{v_n}\over{w_n}} w1v1≥w2v2≥...≥wnvn;
2)若 ∑ i = 1 n w i ≤ S \sum^n_{i=1}w_i\leq{S} ∑i=1nwi≤S,则输出: C G ← ∑ i = 1 n v i C_G\leftarrow{\sum^n_{i=1}v_i} CG←∑i=1nvi,显然此时表示的含义是“物品的总重量不多于背包的容量,可以将物品全部放入”,此时输出的当然就是物品的总价值(因为可以被全部放入背包);
否则求出最大的 k k k,使其满足:
∑ i = 1 k w i ≤ S < ∑ i = 1 k + 1 w i \begin{align*} \sum^k_{i=1}w_i\leq{S}\lt\sum^{k+1}_{i=1}w_i \end{align*} i=1∑kwi≤S<i=1∑k+1wi
上述不等式的含义是,找到最大的 k k k使得无法再放入更多的物品了,即按照“价值-重量比”进行排序的前 k k k个物品放入背包后,背包的剩余容量不足以放入第 k + 1 k+1 k+1个物品了。
输出: C G ← max { v k + 1 , ∑ i = 1 k v i } C_G\leftarrow\max\{v_{k+1}, \sum^k_{i=1}v_i\} CG←max{vk+1,∑i=1kvi}
此时输出结果,取按“价值-重量比”进行排序的前 k k k个物品的价值总和 ∑ i = 1 k v i \sum^k_{i=1}v_i ∑i=1kvi与第 k + 1 k+1 k+1个物品的价值 v k + 1 , v_{k+1}, vk+1,二者之间的最大者。
分析:
从算法的描述来看,0-1背包的2-近似贪心算法过程非常的简单,首先对物品按照 v i w i {v_i\over{w_i}} wivi递减序进行排序,之后分析:如果物品的总重量不大于背包容量,则所有物品都可以被放入;否则,按照物品顺序找到最后一个可以被放入到背包当中的物品的位置 k k k,此时第 k + 1 k+1 k+1个物品再放不进去了,因为再放进去就满了,此时便得到了输出: C G ← max { ∑ i = 1 k w i , v k + 1 } C_G\leftarrow\max\{\sum^k_{i=1}w_i, v_{k+1}\} CG←max{∑i=1kwi,vk+1}。
定理:对于背包问题的一个实例,设opt表示最优解目标函数制, C G C_G CG是由上述算法生成的近似解目标函数值,则 o p t ≤ 2 C G opt\leq2C_G opt≤2CG(近似比为2,近似比的定义为使用算法求得的近似解的目标函数值与最优解的目标函数值之间的比值)
证明:
1)若 ∑ i = 1 n w i ≤ S \sum^n_{i=1}w_i\leq{S} ∑i=1nwi≤S,则 C G = o p t C_G=opt CG=opt:即如果所有物品的重量之和不大于背包容量,则最优解就是所有物品的价值之和;
2)若 ∑ i = 1 n w i > S \sum^n_{i=1}w_i\gt{S} ∑i=1nwi>S,设 k k k是算法得到的整数,可以证明 ∑ i = 1 k v i ≤ o p t < ∑ i = 1 k + 1 v i \sum^k_{i=1}v_i\leq{opt}\lt\sum^{k+1}_{i=1}v_i ∑i=1kvi≤opt<∑i=1k+1vi,证明过程如下:
先放前 k k k个物品进入背包,假定第 k + 1 k+1 k+1个物品是可分割的,将它进行分割来将已经放入了 k k k个物品的背包装满,由于物品的顺序是按照“价值-重量比”递减排序的,第 k + 1 k+1 k+1个物品是没有放入背包的物品当中“价值-重量比”最大的物品,用它的分数来填满背包的剩余空间一定比使用比它顺序更靠后的物品来将背包填满所获得的价值更大。
o p t opt opt小于 ∑ i = 1 k + 1 v i \sum^{k+1}_{i=1}v_i ∑i=1k+1vi,最优值 o p t opt opt上界(非紧)求解:
o p t ≤ c ^ = ∑ i = 1 k v i + v k + 1 w k + 1 ( S − ∑ i = 1 k w i ) < ∑ i = 1 k v i + v k + 1 w k + 1 ⋅ w k + 1 = ∑ i = 1 k + 1 v i C G = m a x { v k + 1 , ∑ i = 1 k v i } ≥ 1 2 ∑ i = 1 k + 1 v i ≥ o p t 2 ( m a x { a , b } ≥ 1 2 ( a + b ) ) \begin{align*} & opt\leq\hat{c}=\sum^k_{i=1}v_i+{{v_{k+1}}\over{w_{k+1}}}(S-\sum^k_{i=1}w_i)\lt\sum^k_{i=1}v_i+{{v_{k+1}}\over{w_{k+1}}}\cdot{w_{k+1}}=\sum^{k+1}_{i=1}v_i \\ & C_G=max\{v_{k+1},\sum^k_{i=1}v_i\}\geq{1\over2}\sum^{k+1}_{i=1}v_i\geq{opt\over2}(max\{a,b\}\geq{1\over2}(a+b)) \end{align*} opt≤c^=i=1∑kvi+wk+1vk+1(S−i=1∑kwi)<i=1∑kvi+wk+1vk+1⋅wk+1=i=1∑k+1viCG=max{vk+1,i=1∑kvi}≥21i=1∑k+1vi≥2opt(max{a,b}≥21(a+b))
证毕。
设 π \pi π是目标函数为 f π f_{\pi} fπ的NP-hard最优化问题,如果关于输入 ( I , ϵ ) (I,\epsilon) (I,ϵ), I I I为 π \pi π的实例, ϵ \epsilon ϵ为误差参数,算法 A A A输出解 S S S使得:
1)若 π \pi π是最小化问题, f π ( I , S ) ≤ ( 1 + ϵ ) ⋅ O P T f_{\pi}(I, S)\leq(1+\epsilon)\cdot{OPT} fπ(I,S)≤(1+ϵ)⋅OPT,目标函数在输入为 I I I的实例下输出解 S S S小于 ( 1 + ϵ ) ⋅ O P T (1+\epsilon)\cdot{OPT} (1+ϵ)⋅OPT
2)若 π \pi π是最大化问题, f p i ≥ ( 1 − ϵ ) ⋅ O P T f_{pi}\geq(1-\epsilon)\cdot{OPT} fpi≥(1−ϵ)⋅OPT
称算法 A A A是NP-Hard优化问题 π \pi π的近似方案。
若对于一个固定的 ϵ > 0 \epsilon\gt0 ϵ>0,算法 A A A的运行时间以实例 I I I的规模的多项式为上界,则称 A A A是一个多项式时间近似算法(简称PTAS)。
在PTAS的基础上,我们进一步要求算法 A A A,即算法 A A A的运行时间以实例 I I I的规模和 1 ϵ {1\over\epsilon} ϵ1的多项式为上界,则称A是一个完全多项式时间近似算法(简称FPTAS)。
无论是多项式时间近似方案PTAS还是完全多项式时间近似方案FPTAS都是 ( 1 + ϵ ) (1+\epsilon) (1+ϵ)-近似算法。
PTAS中对于每一个固定的 ϵ > 0 \epsilon\gt0 ϵ>0,算法 A A A的运行时间以实例 I I I的规模为 n n n的多项式为上界。而FPTAS进一步要求算法 A A A的运行时间以实例 I I I的规模 n n n以及误差参数 1 ϵ 1\over\epsilon ϵ1的多项式为上界。
下面介绍一个0-1背包的伪多项式时间算法:
问题描述:
给定物品集合 S = { a 1 , a 2 , . . . , a n } S=\{a_1, a_2, ..., a_n\} S={a1,a2,...,an},每个物品有指定的大小 s i z e ( a i ) ∈ Z + size(a_i)\in{Z^+} size(ai)∈Z+和指定的收益 p r o f i t ( a i ) ∈ Z + profit(a_i)\in{Z^+} profit(ai)∈Z+,以及背包容量 B ∈ Z + B\in{Z^+} B∈Z+,找一个子集,该子集的总大小以B为上界并且它的总收益最大。
算法思路:
定义 P P P是收益最大的物品的收益, P = m a x a i ∈ S p r o f i t ( a i ) P=max_{a_i\in{S}}profit(a_i) P=maxai∈Sprofit(ai)。
则 n P nP nP是任何解能够获得的收益的平凡上界。(这是显而易见的,用大白话来描述就是对于n个物品,取其中价值最高的物品,设它的价值是P,由于总共有n个物品,它们的总和无论如何也不会比 n P nP nP更大)
对于每个 i ∈ { 1 , . . . , n } i\in\{1,...,n\} i∈{1,...,n}和 p ∈ { 1 , . . . , n P } p\in\{1,...,nP\} p∈{1,...,nP},设 S i , p S_{i,p} Si,p表示 { a 1 , . . . , a i } \{a_1,...,a_i\} {a1,...,ai}的一个子集,该子集的总收益恰好是 p p p,并且它的总大小 S i z e Size Size最小。设 A ( i , p ) A(i, p) A(i,p)表示集合 S i , p S_{i,p} Si,p的大小(如果这样的集合不存在,则 A ( i , p ) = ∞ A(i,p)=\infty A(i,p)=∞)。显然,对于每一个 p ∈ { 0 , 1 , . . . , n P } p\in\{0,1,...,nP\} p∈{0,1,...,nP}, A ( 1 , p ) A(1,p) A(1,p)是已知的。( A ( 1 , p ) A(1, p) A(1,p): S i , p S_{i,p} Si,p中仅包含一个物品,并且物品的收益为 p p p)
由此可以给出递归式:
A ( i + 1 , p ) = min { A ( i , p ) , s i z e ( a i + 1 ) + A ( i , p − p r o f i t ( a i + 1 ) ) } , i f p r o f i t ( a i + 1 ) ≤ p A(i+1, p)=\min\{A(i,p), size(a_{i+1})+A(i,p-profit(a_{i+1}))\}, if\ profit(a_{i+1})\leq{p} A(i+1,p)=min{A(i,p),size(ai+1)+A(i,p−profit(ai+1))},if profit(ai+1)≤p
A ( i + 1 , p ) = A ( i , p ) , o t h e r w i s e A(i+1, p)=A(i,p),otherwise A(i+1,p)=A(i,p),otherwise
Step 1:给定 ϵ > 0 \epsilon\gt0 ϵ>0,设 K = ϵ P n K={{\epsilon{P}}\over{n}} K=nϵP;
Step 2:对每个物品 a i a_i ai,定义 p r o f i t ′ ( a i ) = ⌊ p r o f i t ( a i ) K ⌋ profit'(a_i)=\lfloor{{profit(a_i)}\over{K}}\rfloor profit′(ai)=⌊Kprofit(ai)⌋;
Step 3:用这些值作为物品新的收益,利用前述动态规划算法找到收益最大的集合,记为 S ′ S' S′;
Step 4:输出 S ′ S' S′。
问题描述: 给定n个jobs和m台machines,请设计一个2-近似算法来完成多机调度任务。具体来说,给定n个jobs,处理时间依次为 p 1 , p 2 , . . . , p n p_1,p_2,...,p_n p1,p2,...,pn及整数m,寻找一个方案来将n个jobs分配给m个完全相同的machines,来使得完工时间最短。(多机调度问题是经典的NP-Hard问题)
算法描述: 非常之简单,仅仅分为两步
Step 1:对所有工作按任意顺序排序(即,可以不排序);
Step 2:按次序在机器上对工作进行排序,把下一个工作排序给目前为止被分配了最少量工作的机器。
仅仅简单地使用上述两步便完成了多机调度的2-近似算法。
证明:
多机调度算法OPT解的 L o w e r B o u n d = max { 1 m ( ∑ i = 1 n p i ) , max { p i } } Lower Bound=\max\{{1\over{m}}(\sum^n_{i=1}p_i),\max\{p_i\}\} LowerBound=max{m1(∑i=1npi),max{pi}},即下界要么是所有工作时间之和与机器总数m之比,要么是最长作业时间,取二者中最大值。
设 M i M_i Mi是算法所产生的排序下最后完成的机器,并假设 j j j是排序在这台机器上最后的作业下标。(将作业分配给 M i M_i Mi的原因是,目前为止 M i M_i Mi是被分配了最少量工作的机器,此时除了它之外其它机器都busy)
设作业 j j j的开始时间为 S t a r t j Start_j Startj,显然 S t a r t j ≤ 1 m ∑ k p k ≤ O P T Start_j\leq{1\over{m}}\sum_kp_k\leq{OPT} Startj≤m1∑kpk≤OPT,而又显然有 p j ≤ O P T p_j\leq{OPT} pj≤OPT,将两个不等式相加,得到 S t a r t j + p j ≤ 2 O P T Start_j+p_j\leq2OPT Startj+pj≤2OPT,证毕。
近似比: 算法得到的近似解的目标函数值与最优解的目标函数值之间的比值;
PTAS: 若对于每一个固定的 ϵ > 0 \epsilon\gt0 ϵ>0,算法 A A A的运行时间以实例 I I I的规模的多项式为上界,则称A是一个多项式时间近似方案。
FPTAS: 在PTAS的基础上,我们进一步要求算法 A A A,即算法 A A A的运行时间以实例 I I I的规模和 1 ϵ 1\over\epsilon ϵ1的多项式为上界,则称 A A A是一个完全多项式时间近似方案。