MDeath-Kid

- M I T & Y
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

关于带权中位数的应用总结

Posted on 2011-06-01 11:19  MDeath-Kid  阅读(613)  评论(0编辑  收藏  举报

今天看了几个中位数的题,感觉的确应该好好总结下。

带权中位数的概念:http://baike.baidu.com/view/1209446.htm

中位数要解决的问题:一维平面就是一条直线上汇集到一点的距离的最小值,求这一点。

二维的就是平面上所有点汇集到一点的最小距离,同求这一点。

带权中位数就是这个距离变成了权值。

其实这点满足这个最重要的公式就OK了:

sigma( i=1 to k-1) Wi <= W/2

sigma( i=k+1 to n) Wi <= W/2

但正是这个公式让人头痛,因为公式后面由着大量的证明。

我通俗的在这里说下,有两群人,第一群人共有A个,第二群人共有B个,要求把这两群人合并,使所有人走的最少,求这个步数。如果A>B的话,应该让B走完所有的路径去A,反之一样(可以举例子试试)。这里就是有两群人归纳之N堆时的情况,找到这个临界值。

下面列举一个变种的题。

士兵站队
  
问题:   
   在一个划分成网格的操场上,n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表示。士兵们可以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名士兵。按照军官的命令,士兵们要整齐地列成一个水平队列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何选择x和y的值才能使士兵们以最少的总移动步数排成一列。

算法

#include <iostream> 
#include 
<algorithm> 

using namespace std; 

int x[10000]; 
int y[10000]; 

int main() 

int n; 
cin
>>n; 

for(int i = 0; i < n; ++i) 
cin
>>x[i]>>y[i]; 

int tempx; 
int tempy; 


//带权中位数的第一次用,因为y最后都是一样,所以向y移动的总步数要最少
nth_element(y, y + n / 2, y + n); 
tempy 
= y[n/2]; 

sort(x, x 
+ n); 

 

//x最好是要不一样的,所以先假定他们排成0,1,2,n
for(int i = 0; i < n; ++i) 
x[i] 
-= i; 


//最后剩余的是offset,所以要选一个中位数(对上面的排列进行complete,使其成为最后真正的排列),使得各个offset到这个位置的总步数最少
nth_element(x, x + n / 2, x + n); 
tempx
= x[n/2]; 

int total=0

for(int i = 0; i < n; ++i) 

total 
+= abs(y[i] - tempy); 
total 
+= abs(x[i] - tempx); 
}
 
cout
<<total<<endl; 

}


代码源于网络。

这里有个nth_element(a,n,b)的函数,第一次见到,发现又是个很好的东东。

STL中的nth_element()方法的使用 通过调用nth_element(start, start+n, end) 方法可以使第n大元素处于第n位置(从0开始,其位置是下标为 n的元素),并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,但不能保证他们是有序的。

通俗的说就是去到第几大的元素,而且能够分半放。