vijos p1012题解

原题叙述

弄懂求2维平面最近点对的方法就很简单了。

求最近点对大致如下:

1.以x,y坐标排序,先排x,再y

2.再for i:=1.. n 一遍,找到相邻点之间的距离,以找出相邻点间最短距离min(以便后面的剪枝)

3.分治,即折半查找。

  分为两个点集X,Y,设最近点对为{A,B},有可能有3种情况

    (1)A,B均在X。(2)A,B均在Y。(3)A,B分别在X与Y中

  对于(1)(2),继续分治;对于(3),则以A+B的中间点xm,ym作为轴,找出所有|xi-xm|<min的点进行比较,更新min。

4.输出min

代码如下:

 

type
        point
=record
                x,y:real;
        
end;
var
        n:longint;
        rd:real;
        city,r:
array[0..100000]of point;
procedure swap(var a,b:real);
var
        t:real;
begin
        t:
=a;a:=b;b:=t;
end;
procedure qsort(l,r:longint);
var
        i,j:longint;m:point;
begin
        i:
=l;j:=r;
        m:
=city[random(j-i)+i];
        
repeat
                
while (city[i].x<m.x)or((city[i].x=m.x)and(city[i].y<m.y)) do inc(i);
                
while (city[j].x>m.x)or((city[j].x=m.x)and(city[j].y>m.y)) do dec(j);
                
if i<=then
                        
begin
                                swap(city[i].x,city[j].x);
                                swap(city[i].y,city[j].y);
                                inc(i);dec(j);
                        
end;
        
until i>j;
        
if l<then qsort(l,j);
        
if i<then qsort(i,r);
end;
function dis(a,b:point):real;
begin
        dis:
=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
end;
function min(a,b:real):real;
begin
        
if a<then exit(a) else exit(b);
end;
procedure init;
var
        i,j:longint;
begin
        readln(n);
        
for i:=1 to n do
        
with city[i] do
                readln(x,y);
        qsort(
1,n);
        rd:
=1e10;
        
for i:=2 to n do rd:=min(rd,dis(city[i-1],city[i]));
end;
procedure work(l,r:longint);
var
        i,j,m:longint;d:real;
begin
        m:
=(l+r) shr 1;
        i:
=m;
        
while (l<=i)and(city[m].x-city[i].x<rd) do
                
begin
                        j:
=m+1;
                        
while (j<=r) and( city[j].x-city[m].x<rd) do
                        
begin
                                rd:
=min(rd,dis(city[i],city[j]));
                                inc(j);
                        
end;
                        dec(i);
                
end;
end;
procedure find(l,r:longint);
var
        i,j,t,k,h,mid:longint;d:real;
begin
        
if l=then exit;
        
if l+1=then
                
begin
                        rd:
=min(rd,dis(city[l],city[r]));
                
end;
        work(l,r);

        mid:
=(l+r) div 2;
        find(l,mid);
        find(mid
+1,r);
end;
begin        
        init;
        find(
1,n);
        writeln(rd:
0:3);
end.

 

posted @ 2009-11-03 23:46  瀑布飞鹰  阅读(230)  评论(0编辑  收藏  举报