旋转卡(qia)壳 平面最远点对

这个标题我以前一直读错。。。

旋转卡壳最基本应用便是求平面最远点对,被一对卡壳正好卡住的对应点对称为对踵点(Antipodal point),这里有一个结论,最远点对必然属于对踵点集。

引用别人的证明(加些许自己注解):http://purety.jp/akisame/oi/TJU/

                                     

设∠1+∠2≤180°,∠3+∠4≤180°。那么如果∠1≥∠4,则由于∠1+∠2≤180°,一定可过B、E作两条平行线使边AB落在其中一条上;反之,则可过B、E作两条平行线使DE落在其中一条上(相当于旋转卡壳,是其中某个卡壳与某边重合)。也就是说,当一条线段截凸包所成的两组“同旁内角”之和均不超过180°时,这条线段的两个端点是一对对踵点。因此,若一条线段的两个端点不是对踵点,则必有一组同旁内角之和大于180°。

(图二)因为有一组同旁内角之和大于180°,所以这两个角中必有一个角大于90°(不妨设∠ABE>90°)。这种情况下显然有AE>BE,因此BE不是最远距离点对。也就是说,不是对踵点的点对一定不是最远距离点对,所以最远距离点对一定是对踵点。

有了这些结论和证明,我们便可以轻松解题,提供一个远短于官方代码的版本(三点不共线)。

其中,若凸包为顺时针,cross(st[i],st[j],st[i+1])>cross(st[i],st[j+1],st[i+1]) 要改为"<"。

type point=record x,y:longint; end; var n,ans,top:longint; a,st:array[1..50000]of point; function dist(x,y:point):longint; begin exit(sqr(x.x-y.x)+sqr(x.y-y.y)) end; function cr(x,y:point):longint; begin exit(x.x*y.y-y.x*x.y) end; function check(p0,p1,p2:point):longint; begin exit(cr(p0,p1)+cr(p1,p2)+cr(p2,p0)) end; 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 cross(x,y,z:point):longint; begin exit((y.x-x.x)*(z.y-x.y)-(y.y-x.y)*(z.x-x.x)) end; procedure init; var i,d,j,k:longint; begin readln(n); for i:=1 to n do with a[i] do readln(x,y); qsort(1,n); top:=0; for i:=1 to n do begin while (top>1)and(check(st[top-1],st[top],a[i])<=0) do dec(top); inc(top);st[top]:=a[i] end; k:=top; for i:=n-1 downto 1 do begin while (top>k)and(check(st[top-1],st[top],a[i])<=0) do dec(top); inc(top);st[top]:=a[i] end; if n>1 then dec(top); st[top+1]:=st[1];j:=2;ans:=0; for i:=1 to top do begin while cross(st[i],st[j],st[i+1])>cross(st[i],st[j+1],st[i+1]) do begin inc(j);if j>top then j:=1 end; d:=dist(st[i],st[j]); if d>ans then ans:=d end; writeln(ans) end; begin assign(input,'2187.in');reset(input); init; close(input) end. 

你可能感兴趣的:(旋转卡(qia)壳 平面最远点对)