贪心算法-分数背包问题(Fractional Knapsack Problem)和0-1背包问题(0-1 Knapsack Problem)
目录
-
- 贪心算法简介
- 分数背包问题描述
- 贪心算法求解
-
- 算法简介
- 算法时间复杂度分析
- 正确性证明
-
- 交换论证法简介
- 用交换论证法进行证明
- 讨论:贪心算法用于0-1背包问题
-
- 最坏结果
- 改进后的贪心算法用于0-1背包问题
贪心算法简介
贪心算法(greedy algorithm)总是选择当前看来最佳的选择。贪心算法并不总是给出最优解,但它往往是最简单、最高效的算法。
如果贪心算法能给出最优解,它一定要保证每一轮贪心的结果都是一个最优的子结构,即当前的最优解也是全局最优解的一部分。
分数背包问题描述
情景描述:给定背包容量和一些物品,每个物品有重量和价值两个属性。允许只取一个物品的一部分加入背包,求问如何才能使背包装的物品价值最大。
形式化定义:给定
K
K
K和
W
=
(
w
1
,
w
2
,
.
.
.
,
w
n
)
W=(w_1,w_2,…,w_n)
W=(w1,w2,…,wn),
V
=
(
v
1
,
v
2
,
.
.
.
,
v
n
)
V=(v_1,v_2,…,v_n)
V=(v1,v2,…,vn)。求
X
=
(
x
1
,
x
2
,
.
.
.
,
x
n
)
,
0
≤
x
i
≤
1
X=(x_1,x_2,…,x_n),0\leq x_i\leq1
X=(x1,x2,…,xn),0≤xi≤1,满足
Σ
i
=
0
n
x
i
w
i
≤
K
\Sigma_{i=0}^{n}x_iw_i \leq K
Σi=0nxiwi≤K
使最大化
Σ
i
=
0
n
x
i
v
i
\Sigma_{i=0}^{n}x_iv_i
Σi=0nxivi
该问题实质上是一个线性规划问题,可以用单纯形法、椭球法、内点法(后两者均为多项式时间算法)等求解。但在这个问题中,简单的贪心算法就能够求出最优解。
贪心算法求解
算法简介
核心思想:按性价比(value-per-pound)排序。
- 计算每个物品的单位重量价格
ρ
i
=
v
i
w
i
\rho_i=\frac{v_i}{w_i}
ρi=wivi
- 对
ρ
i
\rho_i
ρi的计算结果按降序排序
- 令
k
=
K
k=K
k=K,表示当前背包的剩余空间
- 每次都选择物品
j
j
j,它具有当前最高的性价比
ρ
j
\rho_j
ρj:
- 如果
w
j
≤
k
w_j\leq k
wj≤k,将重量为
w
j
w_j
wj的
j
j
j物品全部加入背包,
k
=
k
−
w
j
k=k-w_j
k=k−wj;
- 否则将重量为
k
k
k的
j
j
j物品加入背包,迭代结束。
- 如果
算法时间复杂度分析
- 计算性价比为线性复杂度
O
(
n
)
O(n)
O(n)
- 排序可以选用快速排序、堆排序等算法,时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
- 迭代的轮次小于等于
n
n
n,复杂度也为
O
(
n
)
O(n)
O(n)
综上,时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),可见贪心算法在效率上的优势。
正确性证明
这种选择最高性价比的贪心思想的正确性似乎是显然的,但我们还要进行证明。这里用到的方法是交换论证法(exchange argument)。
交换论证法简介
通常用于证明一个贪心算法给出的解是最优解。大致的思想是先假设一个最优解,再将最优解逐步转化为我们算法给出的解,并保证在转化的过程中结果不变差。如果能够完成转化,那么就可以证明贪心算法给出的解也是最优解。
用交换论证法进行证明
假设已经按照
ρ
i
\rho_i
ρi进行了排序,即
ρ
1
≥
ρ
2
≥
.
.
.
≥
ρ
n
\rho_1\geq\rho_2\geq…\geq\rho_n
ρ1≥ρ2≥…≥ρn
记贪心算法的解为
G
=
G=
G=。假设一共装了
i
i
i种物品,则根据我们的求解思路,一定有
x
1
,
.
.
.
,
x
i
−
1
=
1
x_1,…,x_{i-1}=1
x1,…,xi−1=1,而
x
i
≤
1
x_i\leq 1
xi≤1。
假设一个最优解
O
=
O=
O=,显然最优解一定也是填满了背包的,即
Σ
y
i
w
i
=
K
\Sigma y_iw_i=K
Σyiwi=K。
从下标为
1
1
1开始比较方案
G
G
G和
O
O
O,假设第一个不同的值的下标为
j
j
j,即
x
j
≠
y
j
x_j\neq y_j
xj=yj。由于贪心算法的方案每次都尽可能选择最多的量,所以一定有
x
j
≥
y
j
x_j\geq y_j
xj≥yj。假设
x
j
x_j
xj和
y
j
y_j
yj的不同部分为
δ
j
=
x
j
−
y
j
\delta_j=x_j-y_j
δj=xj−yj,那么由于
Σ
x
i
w
i
=
Σ
y
i
w
i
=
K
\Sigma x_iw_i=\Sigma y_iw_i=K
Σxiwi=Σyiwi=K,一定有
Σ
k
=
j
+
1
n
y
k
≥
δ
j
\Sigma_{k=j+1}^ny_k\geq\delta_j
Σk=j+1nyk≥δj。那么就可以从
O
O
O的从
j
+
1
j+1
j+1到
n
n
n的物品中凑出
δ
j
\delta_j
δj的重量重新分配给物品
j
j
j,使得
x
j
=
y
j
+
δ
j
=
y
j
′
x_j=y_j+\delta_j=y’_j
xj=yj+δj=yj′。由于
ρ
j
≥
ρ
j
+
1
,
.
.
.
,
ρ
n
\rho_j\geq \rho_{j+1},…,\rho_n
ρj≥ρj+1,…,ρn,调整后的
O
′
O’
O′方案一定优于或等于原
O
O
O方案。考虑到
O
O
O方案本来就是最优的,那么
O
O
O和
O
′
O’
O′方案一定是等优越性的。
不断重复以上的步骤,就能将最优的
O
O
O方案等优越性地转化为我们的
G
G
G方案,从而证明了我们的方案也为最优的。
讨论:贪心算法用于0-1背包问题
显然,如果在物品不能分割的情况下(即0-1背包问题),以上的贪心算法不一定给出最优解。因为每一次贪心选择不一定在更全局的最优解中。
最坏结果
一个有趣的问题是,如果一定要用贪心算法来解,结果是可以接受的吗?或者说最坏的结果可以有多坏?
首先,我们确定一个衡量方案优越度的指标:
O
P
T
0
−
1
/
A
OPT_{0-1}/A
OPT0−1/A
其中,
O
P
T
0
−
1
OPT_{0-1}
OPT0−1为0-1背包问题的最优解,
A
A
A为其他方案给出的解。这一比值可以衡量方案
A
A
A在一个具体case上的好坏:比值越低,方案越好;如果比值为1,那么方案
A
A
A也为最优解。
考虑如下情况:
K
=
100
K=100
K=100,
W
=
(
100
,
1
)
W=(100,1)
W=(100,1),
V
=
(
100
,
99
)
V=(100,99)
V=(100,99),计算得
ρ
=
(
1
,
99
)
\rho=(1,99)
ρ=(1,99)。按选择最高性价比的贪心算法,应该优先选择物品2,但最优解显然是物品1。最极端的情况是物品2的性价比比物品1略高,但总价值远远低于物品1,这样的
O
P
T
0
−
1
/
A
=
∞
OPT_{0-1}/A=\infin
OPT0−1/A=∞,即最坏情况可以达到任意坏。
改进后的贪心算法用于0-1背包问题
动态规划算法虽然能给出最优解,但在计算效率上远不如贪心算法。能否对贪心算法进行一定的改进,使其在保持效率优越性的情况下保证结果不是太差,比如限制
O
P
T
0
−
1
/
A
≤
2
OPT_{0-1}/A\leq 2
OPT0−1/A≤2?其实是有的,一个简单的改进如下:
假设分数背包问题中,贪心算法选出
i
i
i种物品加入背包,其中
x
1
,
.
.
.
,
x
i
−
1
=
1
x_1,…,x_{i-1}=1
x1,…,xi−1=1,而
x
i
≤
1
x_i\leq 1
xi≤1。那么在相同的0-1背包问题中,比较物品
1
1
1~
i
−
1
i-1
i−1的总价值和
i
i
i的价值,将更大者加入背包。下面证明
O
P
T
0
−
1
/
A
≤
2
OPT_{0-1}/A\leq 2
OPT0−1/A≤2:
我们方案的总价值为
A
=
m
a
x
{
Σ
k
=
1
i
v
k
,
v
i
+
1
}
≥
m
a
x
{
Σ
k
=
1
i
x
k
v
k
,
x
i
+
1
v
i
+
1
}
≥
1
2
(
Σ
k
=
1
i
x
k
v
k
+
x
i
+
1
v
i
+
1
)
=
1
2
(
Σ
k
=
1
i
+
1
x
k
v
k
)
≥
1
2
O
P
T
0
−
1
A=max\{\Sigma_{k=1}^i v_k, v_{i+1}\}\geq max\{\Sigma_{k=1}^i x_kv_k, x_{i+1}v_{i+1}\}\geq \frac{1}{2}(\Sigma_{k=1}^i x_kv_k+x_{i+1}v_{i+1})= \frac{1}{2}(\Sigma_{k=1}^{i+1} x_kv_k)\geq \frac{1}{2}OPT_{0-1}
A=max{Σk=1ivk,vi+1}≥max{Σk=1ixkvk,xi+1vi+1}≥21(Σk=1ixkvk+xi+1vi+1)=21(Σk=1i+1xkvk)≥21OPT0−1。
说明:倒数第二项即为分数背包问题的最优解。而分数背包问题的最优解总是优于或等于相同的0-1背包问题的最优解。因此总有
A
≥
1
2
O
P
T
0
−
1
A\geq \frac{1}{2}OPT_{0-1}
A≥21OPT0−1。
这种近似算法(approximation algorithm)在快速求解复杂问题上往往是很有用的。
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/a65ae9615f.html
