苏海容吧 关注:3贴子:38
  • 1回复贴,共1

凸包问题 (模板对应codevs凸包周长

只看楼主收藏回复

第一次做计算几何的题。。。
凸包:把给定点包围在内部的、面积最小的凸多边形。
Andrew算法是Graham算法的变种,速度更快稳定性也更好。
首先把所有点排序,按照第一关键字x第二关键字y从小到大排序,删除重复点后得到点序列P1...Pn。
1)把P1,P2放入凸包中,凸包中的点使用栈存储
2)从p3开始,当下一个点在凸包当前前进方向(即直线p1p2)左边的时候继续;
3)否则依次删除最近加入凸包的点,直到新点在左边。
如图,新点P18在当前前进方向P10P15的右边(使用叉积判断),因此需要从凸包上删除点P15和P10,让P8的下一个点为P18。重复该过程直到碰到最右边的Pn,求出下凸包即凸包的下轮廓。然后从Pn反过来重复该步骤求出上凸包,合并起来后就是完整的凸包。
http://blog.csdn.net/lytning/article/details/25238347
大神讲的非常好
所谓叉积判断:
已知向量a,b
坐标X1 Y1 X2 Y2
如果x1y2-x2y1<0就是顺时针,大于零逆时针,等于零平行,如果考试的时候忘记了,可以举个例子自己推导一下的。
%%%dubug还以为是凸包方向写错了。。。
下次注意,下不为例
#你的态度我无所谓,我的态度就是坚持下去,继续努力。#


1楼2015-12-22 23:34回复
    忘记附上代码了。。。
    代码实现:
    type hh=record
    x,y:longint;
    end;
    var a:array[1..100001] of hh;
    i,n:longint;
    zhan,zhan1:array[1..50001] of longint;
    pp,p:longint;
    x1,y1,x2,y2,temp:longint;
    ans:double;
    procedure sort1(l,r: longint);
    var
    i,j,x: longint;
    y:hh;
    begin
    i:=l;
    j:=r;
    x:=a[(l+r) div 2].x;
    repeat
    while a[i].x<x do
    inc(i);
    while x<a[j].x do
    dec(j);
    if not(i>j) then
    begin
    y:=a[i];
    a[i]:=a[j];
    a[j]:=y;
    inc(i);
    j:=j-1;
    end;
    until i>j;
    if l<j then
    sort1(l,j);
    if i<r then
    sort1(i,r);
    end;
    procedure sort2(l,r: longint);
    var
    i,j,x: longint;
    y:hh;
    begin
    i:=l;
    j:=r;
    x:=a[(l+r) div 2].y;
    repeat
    while a[i].y<x do
    inc(i);
    while x<a[j].y do
    dec(j);
    if not(i>j) then
    begin
    y:=a[i];
    a[i]:=a[j];
    a[j]:=y;
    inc(i);
    j:=j-1;
    end;
    until i>j;
    if l<j then
    sort2(l,j);
    if i<r then
    sort2(i,r);
    end;
    begin
    readln(n);
    for i:= 1 to n do
    readln(a[i].x,a[i].y);
    sort1(1,n);
    for i:= 1 to n do
    begin
    if a[i].x<>a[i+1].x then if temp=0 then continue;
    if a[i].x=a[i+1].x then if temp<>0 then continue;
    if a[i].x=a[i+1].x then if temp=0 then temp:=i;
    if a[i].x<>a[i+1].x then if temp<>0 then begin sort2(temp,i);temp:=0;end;
    end;
    inc(pp);
    zhan[pp]:=1;
    inc(pp);
    zhan[pp]:=2;
    for i:= 2 to n-1 do
    begin
    x1:=a[zhan[pp]].x-a[zhan[pp-1]].x;
    y1:=a[zhan[pp]].y-a[zhan[pp-1]].y;
    x2:=a[i+1].x-a[zhan[pp]].x;
    y2:=a[i+1].y-a[zhan[pp]].y;
    if x1*y2-x2*y1<0 then
    begin
    inc(pp);
    zhan[pp]:=i+1;
    end
    else
    begin
    repeat
    dec(pp);
    x1:=a[zhan[pp]].x-a[zhan[pp-1]].x;
    y1:=a[zhan[pp]].y-a[zhan[pp-1]].y;
    x2:=a[i+1].x-a[zhan[pp]].x;
    y2:=a[i+1].y-a[zhan[pp]].y;
    until (x1*y2-x2*y1<0) or (pp=1);
    inc(pp);
    zhan[pp]:=i+1;
    end;
    end;
    inc(p);
    zhan1[p]:=n;
    inc(p);
    zhan1[p]:=n-1;
    for i:= n-1 downto 2 do
    begin
    x1:=a[zhan1[p]].x-a[zhan1[p-1]].x;
    y1:=a[zhan1[p]].y-a[zhan1[p-1]].y;
    x2:=a[i-1].x-a[zhan1[p]].x;
    y2:=a[i-1].y-a[zhan1[p]].y;
    if x1*y2-x2*y1<0 then
    begin
    inc(p);
    zhan1[p]:=i-1;
    end
    else
    begin
    repeat
    dec(p);
    x1:=a[zhan1[p]].x-a[zhan1[p-1]].x;
    y1:=a[zhan1[p]].y-a[zhan1[p-1]].y;
    x2:=a[i-1].x-a[zhan1[p]].x;
    y2:=a[i-1].y-a[zhan1[p]].y;
    until (x1*y2-x2*y1<0) or (p=1);
    inc(p);
    zhan1[p]:=i-1;
    end;
    end;
    for i:= 1 to pp-1 do
    ans:=ans+sqrt((a[zhan[i+1]].x-a[zhan[i]].x)*(a[zhan[i+1]].x-a[zhan[i]].x)+(a[zhan[i+1]].y-a[zhan[i]].y)*(a[zhan[i+1]].y-a[zhan[i]].y));
    for i:= 1 to p-1 do
    ans:=ans+sqrt((a[zhan1[i+1]].x-a[zhan1[i]].x)*(a[zhan1[i+1]].x-a[zhan1[i]].x)+(a[zhan1[i+1]].y-a[zhan1[i]].y)*(a[zhan1[i+1]].y-a[zhan1[i]].y));
    writeln(ans:0:1);
    end.


    2楼2015-12-22 23:35
    回复