样例输入输出
ball.in
1
1
0 0
ball.out
0.00
这是一道有关带权中位数(http://www.cnblogs.com/oijzh/articles/2647134.html)的题
分析题目不难发现,xy坐标是不相关的,所以应该离散化分开来,并且最终的目标位置必定在某一个人的点上(如果不在某一个点上,那么必定可以把这个点向左或向右移来找到一个更优的位置!)
了解了带权中位数,这道题就很好做了
Pascal Code
program ball;
type
arr=array[0..500000+10] of longint;
var
n,total:longint;
w,oldw,x,y:arr;
procedure init;
begin
assign(input,'ball.in');
assign(output,'ball.out');
reset(input);
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
halt;
end;
procedure readdata;
var
i:longint;
begin
read(n);
for i:=1 to n do
begin
read(w[i]);
inc(total,w[i]);
end;
for i:=1 to n do read(x[i],y[i]);
end;
procedure swap(var a,b:longint);
var t:longint;
begin
t:=a;a:=b;b:=t;
end;
procedure qs(var a:arr;l,r:longint);
var
i,j,x:longint;
begin
i:=l;j:=r;x:=a[i+(j-i)div 2];
repeat
while a[i]<x do inc(i);
while a[j]>x do dec(j);
if i<=j then
begin
swap(a[i],a[j]);
swap(w[i],w[j]);
inc(i);dec(j);
end;
until i>j;
if i<r then qs(a,i,r);
if l<j then qs(a,l,j);
end;
function workx:double;
var
i,tx:longint;
sum:double;
begin
sum:=0;
for i:=1 to n do
begin
sum:=sum+w[i];
if sum>total/2 then
begin
tx:=x[i];
break;
end;
end;
sum:=0;
for i:=1 to n do
begin
if x[i]=tx then continue;
sum:=sum+w[i]*abs(x[i]-tx);
end;
exit(sum);
end;
function worky:double;
var
i,ty:longint;
sum:double;
begin
sum:=0;
for i:=1 to n do
begin
sum:=sum+w[i];
if sum>total/2 then
begin
ty:=y[i];
break;
end;
end;
sum:=0;
for i:=1 to n do
begin
if y[i]=ty then continue;
sum:=sum+w[i]*abs(y[i]-ty);
end;
exit(sum);
end;
procedure main;
var
xx,yy:double;
begin
oldw:=w;
qs(x,1,n);
xx:=workx;
w:=oldw;//这个一定不能忘了 因为前面排序x的时候已经打乱了w的值!!!
qs(y,1,n);
yy:=worky;
writeln(xx+yy:0:2);
end;
begin
init;
readdata;
main;
outit;
end.