题意
百慕大的每一座城市都坐落在一维直线上。这个国家的政府决定建造一个新的广播电视台。经过了许多次试验后,百慕大的科学家们提出了一个结论,在每座城市的不满意度等于这座城市的市民数与这座城市与广播电视台的距离的乘积。找到这个一维直线上的一点来建造广播电视台,使得所有城市的不满意度的和最小
分析
易证,这个广播电视台必然会建在某个城市点上,否则必然不是最优解
当每个城市都是1个人时,只有当电视台建在中间那个城市,所有人到电视台距离之和才为最小
(奇数个城市时是中间的那个城市;偶数个城市时则为中间两个城市中的任意一个即可。)
但是,每个城市不止一人,该怎么处理呢?
很容易,把每个城市的若干个人拆分成若干个小城市,只不过这些小城市都在同一个坐标而已
这样就可以解决了。
证明:
对于带权中位数的具体证明过程,一下摘自百度百科http://baike.baidu.com/view/1209446.htm
D[I]—第I个点的权值
DIST(I,J)—I到J点的距离,即DIST(I,J)=|NUM[I]-NUM[J]|
由定义式易知:DIST(I,J)=DIST(J,I)
若最优点在T,则有:
DIST(R,T+1)-DIST(R,T)=DIST(T+1,T)
因此:
∑D[L](L<=T)>=∑(D[R])(R>=T+1)
此时我们发现:
也即是说当前的位置T上的数包含了第[(SUMALL)/2]个数,由开篇的简述可知,这第[(SUMALL)/2]个数,就是这个序列中的带权中位数。所以这一类问题,实质上就是带权中位数问题。
Accepted Code
1 /* 2 PROBLEM:sgu114 3 AUTHER:Rinyo 4 MEMO:带权中位数 5 */ 6 #include<cstdio> 7 #include<algorithm> 8 using namespace std; 9 struct rec 10 { 11 double pos; 12 int data; 13 }a[20000]; 14 15 int cmp(rec x,rec y) {return x.pos<y.pos;} 16 int main() 17 { 18 int n; 19 int tot=0,t=0; 20 scanf("%d",&n); 21 for (int i=1;i<=n;i++) 22 { 23 scanf("%lf %d",&a[i].pos,&a[i].data); 24 tot+=a[i].data; 25 } 26 sort(a+1,a+1+n,cmp); 27 tot/=2;tot++; 28 for (int i=1;i<=n;i++) 29 { 30 t+=a[i].data; 31 if (t>=tot) {printf("%lf\n",a[i].pos);break;} 32 } 33 return 0; 34 }