• 算法模板——计算几何2(二维凸包——Andrew算法)


    实现功能:求出二维平面内一对散点的凸包(详见Codevs 1298)

    很神奇的算法——先将各个点按坐标排序,然后像我们所知的那样一路左转,求出半边的凸包,然后反过来求另一半的凸包

    我以前正是因为总抱着想一步到位的想法,所以每次都跪得很惨(HansBug:事实上这次是我这辈子第一次A掉凸包题)

    然后别的没了,就是凸包的基本思想

    (顺便输出凸包周长C和面积S)

     1 type arr=array[0..100005] of longint;
     2 var
     3    i,j,k,l,m,n,m1,m2:longint;
     4    a:array[0..100005,1..2] of longint;
     5    b,c,d:arr;ans,are:extended;
     6 procedure swap(var x,y:longint);
     7           var z:longint;
     8           begin
     9                z:=x;x:=y;y:=z;
    10           end;
    11 procedure sort(l,r:longint);
    12           var i,j,x,y:longint;
    13           begin
    14                i:=l;j:=r;x:=a[(l+r) div 2,1];y:=a[(l+r) div 2,2];
    15                repeat
    16                      while (a[i,1]<x) or ((a[i,1]=x) and (a[i,2]<y)) do inc(i);
    17                      while (a[j,1]>x) or ((a[j,1]=x) and (a[j,2]>y)) do dec(j);
    18                      if i<=j then
    19                         begin
    20                              swap(a[i,1],a[j,1]);
    21                              swap(a[i,2],a[j,2]);
    22                              inc(i);dec(j);
    23                         end;
    24                until i>j;
    25                if i<r then sort(i,r);
    26                if l<j then sort(l,j);
    27           end;
    28 function right(x1,y1,x2,y2:longint):boolean;
    29          begin
    30               exit((x1*y2)>(x2*y1));
    31          end;
    32 function trip(x1,y1,x2,y2,x3,y3:longint):boolean;
    33          begin
    34               exit(right(x2-x1,y2-y1,x3-x2,y3-y2));
    35          end;
    36 function check(x,y,z:longint):boolean;
    37          begin
    38               exit(trip(a[x,1],a[x,2],a[y,1],a[y,2],a[z,1],a[z,2]));
    39          end;
    40 procedure doit(var b:arr;var m:longint);
    41           begin
    42                b[1]:=d[1];b[2]:=d[2];j:=2;
    43                for i:=3 to n do
    44                    begin
    45                         while (j>1) and not(check(b[j-1],b[j],d[i])) do dec(j);
    46                         inc(j);b[j]:=d[i];
    47                    end;
    48                m:=j;
    49           end;
    50 begin
    51      readln(n);
    52      for i:=1 to n do readln(a[i,1],a[i,2]);
    53      sort(1,n);j:=1;
    54      for i:=2 to n do  //去重
    55          begin
    56               if (a[i,1]<>a[j,1]) or (a[i,2]<>a[j,2]) then
    57                  begin
    58                       inc(j);
    59                       a[j,1]:=a[i,1];a[j,2]:=a[i,2];
    60                  end;
    61          end;
    62      n:=j;
    63     //求凸包
    64      for i:=1 to n do d[i]:=i;doit(b,m1);
    65      for i:=1 to n do d[i]:=n+1-i;doit(c,m2);
    66     //两个半边整合
    67      for i:=1 to m1 do d[i]:=b[i];
    68      for i:=2 to m2 do d[i+m1-1]:=c[i];
    69     //开始计算周长+面积
    70      m:=m1+m2-2;ans:=0;are:=0;
    71      for i:=1 to m do ans:=ans+sqrt(sqr(a[d[i],1]-a[d[i+1],1])+sqr(a[d[i],2]-a[d[i+1],2]));  //周长
    72      for i:=1 to m do are:=are+a[d[i],1]*a[d[i+1],2]-a[d[i],2]*a[d[i+1],1];  //面积
    73      are:=abs(are)/2;
    74      writeln('Convex Hull:');
    75      for i:=1 to m do writeln(a[d[i],1],' ',a[d[i],2]);
    76      writeln('C = ',ans:0:1);
    77      writeln('S = ',are:0:1);
    78      readln;
    79 end.
  • 相关阅读:
    c# 如何获取当前方法的调用堆栈(转载)
    被忽视的问题:测试环境配置管理
    性能测试如何创造业务价值
    高级性能测试工程师面试必问十大问题
    Vue随机验证码组件
    面试突击61:说一下MySQL事务隔离级别?
    面试突击60:什么情况会导致 MySQL 索引失效?
    抽奖动画 鲤鱼跳龙门
    VScode 安装PHPdebug新版Xdebug3.0
    Java 项目安全、如何进行安全审计
  • 原文地址:https://www.cnblogs.com/HansBug/p/4442921.html
Copyright © 2020-2023  润新知