• 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.
  • 相关阅读:
    SVN更新的时候前面的子母的意思(A C D M G U R I)
    SQL总结(一)基本查询
    eclipse中如何打开工作空间里面已经有的项目
    java for循环的几种写法
    Eclipse自动生成作者、日期注释等功能设置
    linux任务计划及周期性任务计划
    进程管理工具使用
    Btrfs管理及应用
    LVM基本应用,扩展及缩减实现
    Linux-RAID
  • 原文地址:https://www.cnblogs.com/waterfalleagle/p/1595629.html
Copyright © 2020-2023  润新知