乘客分配问题
- m m m辆公交车,以及其线路、容量 k j k_j kj
- n n n个乘客
乘客分配问题(PAP),就是要决定乘客应该上哪一辆车,使得可以上车的乘客最多,同时不超过公交车的容量上限。
贪心算法
- 输入: m m m, ( S 1 , … , S m ) (S_1,\dots,S_m) (S1,…,Sm), ( k 1 , … , k m ) (k_1,\dots ,k_m) (k1,…,km)
- 输出:每一辆公交车的乘客集合 B 1 , … B m B_1,\dots B_m B1,…Bm
- 对于 j ∈ [ 1 , m ] j\in[1,m] j∈[1,m],初始化所有 B j = ϕ B_j=\phi Bj=ϕ, R j = k j R_j=k_j Rj=kj( R j R_j Rj就是公交车 j j j剩余的容量)
- 当一个乘客
i
i
i到达,其目的地是
d
i
d_i
di:
- j ∗ = a r g m a x j : d i ∈ S j R j j^*=\mathrm{argmax}_{j:d_i\in S_j}R_j j∗=argmaxj:di∈SjRj,也就是在路线包括 d i d_i di的公交车中,选择剩余容量最大的。
- 如果 R j ∗ ≤ 0 R_{j^*}\le 0 Rj∗≤0,则拒绝该乘客;否则,就接受该乘客并更新 B j ∗ ← B j ∗ ∪ { i } B_{j^*}\larr B_{j^*}\cup\{i\} Bj∗←Bj∗∪{i}、 R j ∗ ← R j ∗ − 1 R_{j^*}\larr R_{j^*}-1 Rj∗←Rj∗−1
- 返回 B 1 , … , B m B_1,\dots ,B_m B1,…,Bm
Primal-dual 算法
输入输出与之前相同
- 对于 j ∈ [ 1 , m ] j\in [1,m] j∈[1,m],初始化 B j = ϕ B_j=\phi Bj=ϕ, z j = 0 z_j=0 zj=0
- 当一个乘客
i
i
i到达,其目的地是
d
i
d_i
di:
- j ∗ = a r g m i n j : d i ∈ S j z j j^*=\mathrm{argmin}_{j:d_i\in S_j}z_j j∗=argminj:di∈Sjzj,也就是在路线包括 d i d_i di的公交车中,选择 z j z_j zj最小的。
- 如果 z j ∗ ≤ 1 z_{j^*}\le 1 zj∗≤1,拒绝该乘客;否则更新 B j ∗ ← B j ∗ ∪ { i } B_{j^*}\larr B_{j^*}\cup\{i\} Bj∗←Bj∗∪{i}、 y i ← 1 − z j ∗ y_i\larr 1-z_{j^*} yi←1−zj∗、 z j ∗ ← z j ∗ ( 1 + 1 k j ∗ ) + 1 k j ∗ [ ( 1 + 1 k j ∗ ) k j ∗ − 1 ] z_{j^*}\larr z_{j^*}(1+\frac1{k_{j^*}})+\frac1{k_{j^*}\left[\left(1+\frac1{k_{j^*}}\right)^{k_{j^*}}-1\right]} zj∗←zj∗(1+kj∗1)+kj∗[(1+kj∗1)kj∗−1]1
- 返回 B 1 , … B m B_1,\dots B_m B1,…Bm
竞争比
O P T ( I ) \mathrm{OPT}(\mathcal{I}) OPT(I)是对于实例 I \mathcal{I} I最优的可行解。对于在线算法问题,实例是分块给出的。
一个在线算法 A \mathcal{A} A是 c c c竞争比的,即对于任意一个实例 I \mathcal I I:
- 其cost都要小于等于 c ⋅ O P T ( I ) + α c\cdot \mathrm{OPT}(\mathcal I)+\alpha c⋅OPT(I)+α
- 其cost都要大于等于 O P T c ( I ) − α \frac{ \mathrm{OPT}}{c}(\mathcal I)-\alpha cOPT(I)−α
其中 c ≥ 1 c\ge 1 c≥1, α \alpha α是独立于请求序列的。如果有 α = 0 \alpha=0 α=0,则称是严格 c c c竞争比的。
分页问题
分页算法
- LRU(Least Recently Used):移除距今最远被访问的分页。
- FIFO(First-in First-out):先进先出
- LFU(Least Frequency Used):维护一个引用计数器,计数器最少的被移除
- OPT(Furtherest in the Future):将在未来最后一个被访问的分页进行移除(最优解,不可能实现)
LRU和FIFO的竞争比
结论
LRU和FIFO的竞争比是 K K K,其中 K K K就是slot的数量。
证明
定义 σ \sigma σ是分页的请求序列。将请求序列按照以下规则进行分块:每一块正好有 K K K个不同种类的分页请求。( σ = σ 1 σ 2 σ 3 … \sigma=\sigma_1\sigma_2\sigma_3\dots σ=σ1σ2σ3…,其中 σ i \sigma_i σi就是一个块)
比如有
σ
=
1
,
2
,
3
,
2
,
4
,
2
,
5
,
2
,
1
,
2
,
1
,
3
,
1
,
…
\sigma=1,2,3, 2, 4, 2, 5, 2, 1, 2, 1, 3, 1,\dots
σ=1,2,3,2,4,2,5,2,1,2,1,3,1,…,
K
=
3
K=3
K=3,则有:
σ
1
=
1
,
2
,
3
,
2
σ
2
=
4
,
2
,
5
,
2
σ
3
=
1
,
2
,
1
,
3
,
1
\begin{aligned} \sigma_1&=1,2,3,2\\ \sigma_2&=4,2,5,2\\ \sigma_3&=1,2,1,3,1 \end{aligned}
σ1σ2σ3=1,2,3,2=4,2,5,2=1,2,1,3,1
在每一个块里面,LRU算法和FIFIO算法至多出现 K K K次缺页错误(移除一个分页)。(因为发生了 K K K次缺页错误之后,就到了下一个块)
(考虑一个可能会出现 K K K次错误的情况,对于 K = 3 K=3 K=3,现在slot里面有 1 , 2 , 3 1,2,3 1,2,3(上一个块的顺序也是 1 , 2 , 3 1,2,3 1,2,3),对于 4 , 1 , 2 4,1,2 4,1,2,LRU和FIFO都会有3次缺页错误(分别移出 1 , 2 , 3 1,2,3 1,2,3),而最优算法只会有1次缺页错误(只移出 3 3 3))
至此得到了在线算法的cost,即 L R U ≤ K ⋅ t \mathrm{LRU}\le K\cdot t LRU≤K⋅t
对于最优算法的cost,定义shifted block σ i ′ = ( σ i − P i ) ∪ P i + 1 \sigma'_i=(\sigma_i-P_i)\cup P_{i+1} σi′=(σi−Pi)∪Pi+1,其中 P i P_i Pi是 σ i \sigma_i σi的第一个分页请求。其实根据块的定义就很容易看出,对于每一个块的第一个请求,肯定是会和上一个块冲突。因此对于每一个shifted block,都至少会发生一次缺页错误。(也就是块的分解一定会有一次错误)
(我们不需要考虑,最优算法还有哪里可能会有错误。我们已经得到了一个下界)
因此得到最优算法的cost O P T ≥ t − 1 \mathrm{OPT}\ge t-1 OPT≥t−1,其中 t t t是块的数量。
根据之前得到的 L R U ≤ K ⋅ t \mathrm{LRU}\le K\cdot t LRU≤K⋅t,就可以得到LRU算法是 K K K竞争比的。对于FIFO同理。
竞争比是否已经最优?
结论
所有确定的分页算法都是至少 K K K竞争比的。
证明
(对手策略)
不失一般性,记 n = K + 1 n=K+1 n=K+1,其中 n n n是分页的种类总数。对于一般的算法 A \mathcal A A,我们都可以构造出一个 σ \sigma σ,使得每一个请求都正好缺页。而对于最优算法,每 K K K个请求最多只发生一次缺页异常。
线性搜索
问题描述
假设你是一头饥饿的牛,在一条有两个方向的道路上,道路的某一个位置有草可以吃。你只有真正的到了那个有草的位置,才知道这个位置有草(类似于在线算法条件的到来是不确定的)。
记 D > 1 D>1 D>1是实际上那个有草的地方距离你起始点的距离。请设计一个策略,使得找到草所需要走过的最大距离不超过 9 D 9D 9D。
加倍算法
- 初始化 d = 1 d=1 d=1,随便向一个方向走。
- 重复一下过程:
- 沿着当前方向走 d d d的距离
- 如果找到了草,就成功退出;如果没有找到草,就将 d d d翻倍,回到起始位置,朝着相反的方向继续
证明
最坏的情况就是,有牧草的地方刚好就在你“放弃尝试”的位置的正前方。不失一般性地,我们定义:
O P T = 2 j + ε > 2 j \mathrm{OPT}=2^j+\varepsilon >2^j OPT=2j+ε>2j
其中 j j j就是迭代的次数。
那么在线算法的cost之和就是:
A L G = 2 ⋅ ∑ i = 0 j + 1 2 i + 2 j + ε = 2 ⋅ ( 2 j + 2 − 1 ) + 2 j + ε = 9 ⋅ ( 2 j + ε ) − ( 8 ⋅ ε + 2 ) < 9 ⋅ O P T \begin{aligned} \mathrm{ALG}&=2\cdot \sum_{i=0}^{j+1}2^i+2^j+\varepsilon\\ &=2\cdot(2^{j+2}-1)+2^j+\varepsilon\\ &=9\cdot(2^j+\varepsilon)-(8\cdot\varepsilon+2) &<9\cdot \mathrm{OPT} \end{aligned} ALG=2⋅i=0∑j+12i+2j+ε=2⋅(2j+2−1)+2j+ε=9⋅(2j+ε)−(8⋅ε+2)<9⋅OPT
(练习)一个一个地将符号读入数组
问题描述
对于一个长度未知的非空字符串 s ∈ Σ + s\in \Sigma^+ s∈Σ+,将其中的符号存到一个连续的数组里面。约束数组的最大长度不能超过 2 ∣ s ∣ 2|s| 2∣s∣。读入一个符号的cost是 1 1 1。数组可能会越界,因此需要进行扩容,当前旧数组中如果有 k k k个符号,那么复制过去的代价就是 k k k。
考虑这样的一个在线算法:数组的初始大小是 1 1 1,每一次越界,新数组的大小都是原数组大小的 2 2 2倍。则该算法的竞争比是 3 3 3。