Description
经过多年的积蓄,农夫JOHN决定造一个新的牛舍。他知道所有N(2 <= N <= 10,000)头牛的吃草位置,所以他想把牛舍造在最方便的地方。每一头牛吃草的位置是一个整数点(X_i, Y_i) (-10,000 <= X_i <= 10,000; -10,000 <= Y_i <= 10,000)。 没有两头牛的吃草位置是相邻的。 JOHN决定把牛舍造在一个没有牛吃草的整数点上。如果牛舍在(X, Y),在(X_i, Y_i)的牛到牛舍的距离是|X-X_i|+|Y-Y_i|。 JOHN把牛舍造在哪儿才能使所有牛到牛舍的距离和最低?
Input
第1行: 一个数,N。第2~N+1行:第i+1行 包含第i头牛的位置(X_i, Y_i)。
Output
第1行: 两个数,最小距离和和所有可能达到这个距离和的牛舍位置的数目。
Sample Input
4
1 -3
0 1
-2 1
1 -1
输入解释:
一共有4头牛,位置分别为(1, -3), (0, 1), (-2, 1), 和(1, -1).
1 -3
0 1
-2 1
1 -1
输入解释:
一共有4头牛,位置分别为(1, -3), (0, 1), (-2, 1), 和(1, -1).
Sample Output
10 4
输出解释:
最小距离和是10,可以在牛舍位于 (0, -1), (0, 0), (1, 0), (1, 1)时达到。
输出解释:
最小距离和是10,可以在牛舍位于 (0, -1), (0, 0), (1, 0), (1, 1)时达到。
题目大意:在二维平面内找一个不与一直点重合的点使得给出点到该点的距离最短。
距离d=abs(x[i]-x)+abs(y[i]-y) (1<=i<=n)
对于所有点的距离,可以理解成x方向的距离和y方向的距离,而且这两个距离是相互独立的。可以看成求两个方向的最大化问题。
这样就可以很容易看出来,对于确定最小点o的x坐标,如果是偶数个点,就找出最接近中位数的两个坐标,则o的坐标落在这之间,y坐标同理可求。对于奇数个点,o的x,y坐标唯一确定,但有可能和奶牛重合,那么只要扫一遍周围四个点即可。
AC CODE
program
hy_1696;
var
x,y,a:
array
[
1..10000
]
of
longint
;
n,x1,x2,y1,y2,x0,y0,tmp,ans,i:
longint
;
//============================================================================
procedure
qsort(l,r:
longint
);
var
k,i,j,t:
longint
;
begin
k:=a[(l+r)
shr
1
]; i:=l; j:=r;
repeat
while
a[i]<k
do
inc(i);
while
a[j]>k
do
dec(j);
if
i<=j
then
begin
t:=a[i]; a[i]:=a[j]; a[j]:=t;
inc(i); dec(j);
end
;
until
i>j;
if
j>l
then
qsort(l,j);
if
i<r
then
qsort(i,r);
end
;
//============================================================================
procedure
find(g,h:
longint
);
var
i:
longint
;
begin
tmp:=
0
;
for
i:=
1
to
n
do
tmp:=tmp+
abs
(x[i]-g)+
abs
(y[i]-h);
end
;
//============================================================================
procedure
walk;
var
i,len,ans,area:
longint
;
begin
x0:=x1; y0:=y1; len:=
0
;
area:=(x2-x1+
1
)*(y2-y1+
1
);
for
i:=
1
to
n
do
begin
len:=len+
abs
(x[i]-x0)+
abs
(y[i]-y0);
if
(x[i]>=x1)
and
(x[i]<=x2)
and
(y[i]>=y1)
and
(y[i]<=y2)
then
dec(area);
end
;
if
area>
0
then
writeln
(len,
' '
,area)
else
begin
ans:=maxlongint; area:=
0
;
find(x0,y0-
1
);
if
tmp<ans
then
begin
ans:=tmp; area:=
1
;
end
else
if
tmp=ans
then
inc(area);
find(x0-
1
,y0);
if
tmp<ans
then
begin
ans:=tmp; area:=
1
;
end
else
if
tmp=ans
then
inc(area);
find(x0,y0+
1
);
if
tmp<ans
then
begin
ans:=tmp; area:=
1
;
end
else
if
tmp=ans
then
inc(area);
find(x0+
1
,y0);
if
tmp<ans
then
begin
ans:=tmp; area:=
1
;
end
else
if
tmp=ans
then
inc(area);
writeln
(ans,
' '
,area);
end
;
end
;
//============================================================================
begin
readln(n);
for
i:=
1
to
n
do
readln(x[i],y[i]);
for
i:=
1
to
n
do
a[i]:=x[i]; qsort(
1
,n);
if
odd(n)
then
begin
x1:=a[n
shr
1
+
1
];
x2:=x1;
end
else
begin
x1:=a[n
shr
1
];
x2:=a[n
shr
1
+
1
];
end
;
for
i:=
1
to
n
do
a[i]:=y[i]; qsort(
1
,n);
if
odd(n)
then
begin
y1:=a[n
shr
1
+
1
];
y2:=y1;
end
else
begin
y1:=a[n
shr
1
];
y2:=a[n
shr
1
+
1
];
end
;
walk;
end
.