zoukankan      html  css  js  c++  java
  • Tyvj1462 细节凸包

    P1462终于过了……说起来只是一个简单的凸包却交了7次,足见此题数据之严。

    我使用的是graham scan。先找到y坐标最小,若y相同x最小点【注1】的坐标作为起始点P0,显然其他点与P0的极角属于[0,pi](此极角用arctan计算,特殊处理x=0与(x<0) and (y=0)时【注2】。注意pascal的arctan返回值是(-pi/2,pi/2)……)。按极角从大到小,若极角相同则按至P0点距离由小到大【注3】排序。

    处理工作完成后,将P0与P1压入栈,之后循环处理P2~Pn-1栈顶 - I栈顶-1 - 栈顶 向量的左侧或平行(你应该知道什么叫做叉积)则退栈,注意限定Stacksize>=2【注4】。最后将I压入栈。

    之后找题目要求的找到起始点开始输出即可。注意精度【注5】

     

    【注1】

    网上的graham scan 教程均这么认为,但经测试若按本算法没有x限制亦可。

    【注2】

    RTE&WA了请参照此两者。分别为pi/2和 pi。尤其是后者容易忘记考虑。

    【注3】

    由于之后两向量共线即退栈,要保证一条线上的点最远点能得以保留,则其应(在这些共线点中)最后处理。

    数据

    Input

    5

    0 0

    1 2

    1 0

    0 2

    0 1


    Output

    0.0000 0.0000
    0.0000 2.0000
    1.0000 2.0000
    1.0000 0.0000

    【注4】全部共线时不限定栈大小会导致栈元素小于2,导致RTE。

    【注5】pascal请用extended。同时写一个cmp函数。a>b改写成a-b>1e-12,依此类推。

    附赠几组数据(删减版):

    #1

    Input

    15
    372048554 194840794
    1493722368 1609046412
    764185136 846253213
    1495038584 704170204
    239709973 1230989664
    908965419 1067337718
    1296315630 717326987
    576635090 1685913746
    1232082109 1060706659
    653622963 1534768490
    448977811 741758128
    244213649 77154157
    911904634 230031831
    1614797846 889031095
    241142922 1949120387

    Output

    239709973.0000 1230989664.0000
    241142922.0000 1949120387.0000
    1493722368.0000 1609046412.0000
    1614797846.0000 889031095.0000
    1495038584.0000 704170204.0000
    911904634.0000 230031831.0000
    244213649.0000 77154157.0000

    #2

    Input

    4

    1 1

    2 2

    3 3

    4 4

    Output

    1.0000 1.0000
    4.0000 4.0000

     Code:

    program p1462;
    
    Const
     eps=1e-15;
    
    Type
     Point=record
       x,y:extended;
     end;
     Vector=Point;
    
    Var
     a,b:array[0..100002] of point;
     ans:array[0..100002] of longint;
     n,i,low,top:longint;
    
    Function len(a:vector):extended;inline;begin len:=sqrt(sqr(a.x)+sqr(a.y)); end;
    Function Dot(a,b:vector):extended;inline;begin dot:=a.x*b.x+a.y*b.y; end;
    Function cos(a,b:vector):extended;inline;begin cos:=dot(a,b)/len(a)/len(b); end;
    Function cross(a,b:vector):extended;inline;begin cross:=a.x*b.y-a.y*b.x; end;
    Function cmp(a:extended):longint;inline;begin if a>eps then exit(1);if a<-eps then exit(-1);exit(0); end;
    Function minus(a,b:vector):vector;inline;begin minus.x:=a.x-b.x;minus.y:=a.y-b.y; end;
    Function cos(A:vector):extended;inline;begin cos:=a.x/len(a); end;
    Function angle(A:vector):extended;inline;var y:extended;begin if cmp(a.x)=0 then exit(pi/2);if (cmp(a.x)<0) and (cmp(a.y)=0) then exit(pi); y:=arctan(a.y/a.x);if cmp(y)<0 then exit(y+pi) else exit(y); end;
    
    Procedure qsort(l,r:longint);
    var
     i,j:longint;
     x,y:point;
      begin
      i:=l;j:=r;x:=b[(l+r) div 2];
        repeat
        while (cmp(angle(minus(b[i],b[1]))-angle(minus(x,b[1])))>0) or ((cmp(angle(minus(b[i],b[1]))-angle(minus(x,b[1])))=0) and (len(minus(b[i],b[1]))<len(minus(x,b[1])))) do inc(i);
        while (cmp(angle(minus(b[j],b[1]))-angle(minus(x,b[1])))<0) or ((cmp(angle(minus(b[j],b[1]))-angle(minus(x,b[1])))=0) and (len(minus(b[j],b[1]))>len(minus(x,b[1])))) do dec(j);
        if i<=j then
          begin
          y:=b[i];
          b[i]:=b[j];
          b[j]:=y;
          inc(i);
          dec(j);
        end;
      until i>j;
      if l<j then qsort(l,j);
      if i<r then qsort(i,r);
    end;
    
    Procedure push(P:longint);
      begin
      inc(top);
      ans[top]:=p;
    end;
    
      begin
      readln(n);
      for i:=1 to n do
        readln(a[i].x,a[i].y);
      low:=1;
      for i:=2 to n do
        if (a[i].y<a[low].y) or ((a[i].y=a[low].y) and (a[i].x>a[low].x)) then
          low:=i;
      top:=1;
      for i:=1 to n do
        if i<>low then
          begin
          inc(top);
          b[top]:=a[i];
        end;
      b[1]:=a[low];
      qsort(2,n);
      top:=0;
      push(1);push(2);
      for i:=3 to n do
        begin
        while (cmp(cross(minus(b[ans[top]],b[ans[top-1]]),minus(b[i],b[ans[top]])))>=0) and (top>=2) do dec(top);
        push(i);
      end;
      low:=1;
      for i:=2 to top do
        if (b[ans[i]].x<b[ans[low]].x) or ((b[ans[i]].x=b[ans[low]].x) and (b[ans[i]].y<b[ans[low]].y)) then low:=i;
      for i:=low to top do writeln(b[ans[i]].x:0:4,' ',b[ans[i]].y:0:4);
      for i:=1 to low-1 do writeln(b[ans[i]].x:0:4,' ',b[ans[i]].y:0:4);
    
    end.
    
  • 相关阅读:
    2020软件工程作业00——问题清单
    2020软件工程作业03
    2020软件工程作业02
    2020软件工程作业01
    2020软件工程个人作业06——软件工程实践总结作业
    2020软件工程作业00
    2020软件工程作业03
    2020软件工程作业02
    2020软件工程作业01
    2020软件工程个人作业06——软件工程实践总结作业
  • 原文地址:https://www.cnblogs.com/htfy/p/3067884.html
Copyright © 2011-2022 走看看