邮局问题的相关讨论

来源:互联网 发布:node书籍 编辑:程序博客网 时间:2024/05/17 09:26

 我先简要说明一下题意:

    在一维坐标轴上,有n个村庄,要把选一个邮局建在某个村庄上。要满足一个要求:各个村庄到达这个邮局的距离之和的总和要最小。求邮局的最佳选址。

一:论证邮局问题的最优解是带权中位数:

先了解一些符号的意思:

D[I]I个点的权值   

DIST(IJ)IJ点的距离,即DIST(IJ)=|NUM[I]-NUM[J]  

由定义式易知:DIST(IJ)=DIST(IJ)

若最优点在  

则有:   

{D[I]*DIST(IT)}(I<>T) <= {D[I]*DIST(I,T+1)}(I<>T+1)

//最优点的到点的距离之和明显不大于其他点的,当然T+1也不例外。

{D[L]}*DIST(L,T)}+{D[R]*DIST(R,T)}+D[T+1]*DIST(T+1,T)   <=∑{D[L]}*DIST(L,T+1)}+∑{D[R]*DIST(R,T+1)}+D[T]*DIST(T,T+1) (L<T&R>T+1) 

//所有点到可以分成三类:T左边的点为L类,T+1右边的点为R类,TT+1点自成一类。

整理得:

∑{D[L]*DIST(L,T+1)}-∑{D[L]*DIST(L,T)}(L<T)+D[T]*(DIST(T,T+1))>=∑{D[R]*DIST(R,T)}-∑(D[R]*DIST(R,T+1))(R>T+1)+D[T+1]*(DIST(T,T+1))

//将于L相关的放在一边,与R相关的放在另一边。

{D[L]*(DIST(L,T)-DIST[L,T+1])}(L<=T)<={D[R]*(DIST(R,T+1)-DIST(R,T))}(R>=T+1)

//这里要注意的是TR的定义已经发生了变化,L<=T R>=T+1。定义的变化是为式子更加整洁。然后将上式子两边同乘以-1,并且把公因数提取出来。

因为

  DIST(L,T)-DIST(L,T+1)=DIST(T,T+1) 

  DIST(R,T+1)-DIST(R,T)=DIST(T+1,T)

      DIST(T,T+1)=DIST(T+1,T)

所以

{D[L]*DIST(T,T+1)*(-1)(L<=T)<={D[R]*DIST(T+1,T)

*(-1)}(R>=T+1)

D[L](L<=T)>=(D[R])(R>=T+1)   

//两边消掉DIST(T,T+1)*(-1)

即:D[L](L<T)+D[T]>=(D[R])(R>T) 

而类似的,我们可以证明其右边的权值和加上D[T]后大于左边的权值和,只要将第一步改成:

{D[I]*DIST(IT)}(I<>T) <= {D[I]*DIST(I,T-1)}(I<>T-1)

其他的步骤类似。

因为左边的权值和数+D[T]>=右边的权值和,那么:   LEFTSUM+D[T]>=RIGHTSUM=SUMALL-(LEFTSUM+D[T])   =>2*(LEFTSUM+D[T])>=SUMALL   =>2*RIGHTSUM<=SUMALL 

同理可得: 2*LEFTSUM<=SUMALL 

综上所述:

RIGHTSUM <= SUMALL/2

LEFTSUM<=SUMALL/2

很明显,我们假设的最优点既是带权中位数。

证毕。

二:求出n个元素的带权中位数:

思路:

SUM1..n号元素的和。

    先假设带权中位数就是val[n/2],通过遍历1..n/2-1求出他们的和leftSum

同理n/2+1..n号元素的和为rightSum

如果leftSum < SUM /2 且 rightSum < SUM / 2, 那么显然val[n/2]必然为带权中位数。

当 leftSum > SUM / 2,带权中位数必然在左边,因为如果在右边,那么leftSum依然大于SUM / 2,矛盾。

此时把权重rightSum加到val[n/2]的权重上,我们不必关心每个值的具体权重,因为对带权中位数而言,右边的val的权重的和只要不变,就对它毫无影响。而val[n/2]一定在带权中位数右边,所以可以把权重rightSum加到val[n/2]的权重上。

此时只要递归从1..n/2中找即可。

如果rightSum > SUM /2 且 leftSum < SUM / 2,道理是一样的。

复杂度分析:

计算SUM.  O(n)

递归找带权中位数: 

T(n) = O(n) + O(n/2) + O(n/4) + O(n/8)..O(n/2i) + T(n/2i+1)

令n/2i+1 = 1

所以T(n/2i+1) = T(1)

所以T(n) = c * (n + n/2 + n/4 ...n/2i) + T(1) < 2 * cn + 1 = O(n)

综上所述

    O(n) + T(n) < O(n) * 2 = O(n)

伪代码就不写了,很容易百度出来。