扫描线法(水平序)求凸包

还有一种极角序,但有很多细节要考虑,难实现。

好像扫描线只能解决二维凸包,快包无论是最差复杂度,期望复杂度,高维推广都比扫描线优秀,但我暂时不会。

推荐http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html

算法思想:

1、按y为以一关键字,x为2关键字排序。

2、用栈维护凸壳,左下点和右上点一定在凸包上,分别求上下凸壳,用叉积判断凸性。

叉积求面积也很方便。

type point=record x,y:longint; end; var a:array[1..10000]of point; st:array[1..10000]of longint; top,ans,n:longint; procedure qsort(l,r:longint); var i,j,x,y:longint; c:point; begin i:=l;j:=r;y:=a[(l+r)>>1].y;x:=a[(l+r)>>1].x; repeat while (a[i].y<y)or((a[i].y=y)and(a[i].x<x)) do inc(i); while (y<a[j].y)or((y=a[j].y)and(x<a[j].x)) do dec(j); if not(i>j) then begin c:=a[i];a[i]:=a[j];a[j]:=c; inc(i);dec(j) end until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r) end; function cr(x,y:point):longint; begin exit(x.x*y.y-y.x*x.y) end; function check(p0,p1,p2:point):boolean; begin if cr(p1,p2)+cr(p2,p0)+cr(p0,p1)<=0 then exit(true); exit(false) end; procedure init; var i,tot,k:longint; begin readln(n); for i:=1 to n do with a[i] do readln(x,y); qsort(1,n); top:=0;fillchar(st,sizeof(st),0); for i:=1 to n do begin while (top>1)and check(a[st[top-1]],a[st[top]],a[i]) do dec(top); inc(top);st[top]:=i end; k:=top; for i:=n-1 downto 1 do begin while (top>k)and check(a[st[top-1]],a[st[top]],a[i]) do dec(top); inc(top);st[top]:=i end; if n>1 then dec(top); ans:=0;tot:=0; for i:=1 to top-1 do tot:=tot+(a[st[i]].x*a[st[i+1]].y)-(a[st[i+1]].x*a[st[i]].y); tot:=tot+(a[st[top]].x*a[st[1]].y-a[st[1]].x*a[st[top]].y); ans:=abs(tot)>>1; writeln(trunc(ans/50)) end; begin assign(input,'3348.in');reset(input); init; close(input) end.  

你可能感兴趣的:(扫描线法(水平序)求凸包)