Zju 2419 Triangle [凸包] 解题报告

http://andyzh1314.ycool.com/post.1050679.html

 

Zju 2419 Triangle [凸包] 解题报告

 

算法是先寻找凸包,然后对凸包枚举其中一点,在枚举凸包中的另一点,第三点随着第二点的变化而变化。

我们知道最优三角形的三个点一定在凸包上,下面我们证明一下:

假设我们有最优三角形ABC中存在点不在凸包上,不妨设之为A,那么必然在凸包上存在三个点包含A点,过A点作BC的平行线l ,此平行线要么与凸包的一条边重合,那么这点可以算在凸包上,否则必有交点,那么凸包上必存在一点PA在直线l的异侧。那么我们得到三角形PBC的面积大于三角形ABC的面积,三角形ABC不是最优三角形。

故三角形的三个顶点一定在凸包上。

我的程序如下:

PROGRAM p2319;

TYPE

        PosType=record

                x,y             :Longint;

        end;

VAR

        n                       :Longint;

        line                    :array[1..50000]of PosType;

        ball                    :array[0..50000]of Longint;

PROCEDURE Change(var a,b:PosType);

var

        temp                    :PosType;

begin

temp:=a;

a:=b;

b:=temp;

end;

PROCEDURE Readin;

var

        min,i,num_miny          :Longint;

begin

min:=9999999;

for i:=1 to n do

        with line[i] do

                begin

                readln(x,y);

                if y<min then

                        begin

                        min:=y;

                        num_miny:=i;

                        end;

                end;

Change(line[1],line[num_miny]);

for i:=2 to n do

        with line[i] do

                begin

                x:=x-line[1].x;

                y:=y-line[1].y;

                end;

with line[1] do

        begin

        x:=0;

        y:=0;

        end;

end;

Function compare(var a,b:PosType):Longint;

begin

compare:=a.y*b.x-a.x*b.y;

end;

PROCEDURE Sort(left,right:Longint);

var

        mid,i,j                         :Longint;

        key,temp                        :PosType;

begin

key:=line[left];

i:=left-1; j:=right+1;

repeat

        repeat dec(j); until compare(line[j],key)<=0;

        repeat inc(i); until compare(line[i],key)>=0;

        if (i<j) then

                begin

                temp:=line[i];

                line[i]:=line[j];

                line[j]:=temp;

                end else break;

until false;

if (j+1<right) then Sort(j+1,right);

if (left<i-1) then Sort(left,i-1);

end;

FUNCTION Check(v:Longint):Boolean;

var

        a,b                     :PosType;

        mul                     :Longint;

begin

with a do

        begin

        x:=line[ball[ball[0]-1]].x-line[ball[ball[0]]].x;

        y:=line[ball[ball[0]-1]].y-line[ball[ball[0]]].y;

        end;

with b do

        begin

        x:=line[v].x-line[ball[ball[0]]].x;

        y:=line[v].y-line[ball[ball[0]]].y;

        end;

if a.x*b.y-b.x*a.y>0 then Check:=true

        else Check:=false;

end;

PROCEDURE Main;

var

        i,j,k                   :Longint;

        a,b,c                   :Longint;

        temp                    :PosType;

        ans,first,second        :Extended;

        Function area(var a,b,c:Longint):Extended;

        begin

        area:=abs(

        (line[a].x-line[b].x) * (line[c].y-line[b].y)

                                -(line[a].y-line[b].y) * (line[c].x-line[b].x));

        end;

begin

Sort(2,n);

ball[0]:=2;

ball[1]:=1;

ball[2]:=2;

for i:=3 to n do

        begin

        while check(i) do

                dec(ball[0]);

        inc(ball[0]);

        ball[ball[0]]:=i;

        end;

ans:=-1;

first:=0;

k:=0;

for i:=1 to ball[0] -2 do

        begin

        dec(k,200);

        for j:=i+1 to ball[0] -1 do

                begin

                if (k<=j) then k:=j+1;

                first:=area(ball[i],ball[j],ball[k]);

                if first>ans then ans:=first;

                while (k+1<=ball[0]) do

                        begin

                        second:=area(ball[i],ball[j],ball[k+1]);

                        if second<first then break;

                        inc(k);

                        first:=second;

                        if first>ans then ans:=first;

                        end;

                end;

        end;

{for i:=1 to n do

        for j:=i+1 to n do

                for k:=j+1 to n do if area(i,j,k)> ans then ans:=area(i,j,k);

}

ans:=ans / 2;

writeln(ans:0:2);

end;

BEGIN

readln(n);

while (n>0) do

        begin

        Readin;

        Main;

        readln(n);

        end;

END.

 

posted @ 2008-12-05 14:54  jesonpeng  阅读(175)  评论(0)    收藏  举报