【凸包】含共线判定O(N^2)
Vijos P1253
@.@多边形面积
描述 Description
在直角坐标系中,给出n个顶点的坐标,求这n个点所围成的图形的周长和面积。
注意:
(1)如果所有点共线则周长按直线的长度计算,面积视为0;
(2)如果部分点共线按共线后的多边形计算;
(3)所给出的n个顶点如果能围成多边形均为突多边形。
输入格式 Input Format
第一行输入多边形顶点个数n(3<=n<=10);
接下来n行每行输入一个顶点坐标x,y,x,y均为整数且坐标的绝对值均不超过10。
输出格式 Output Format
两行,即多边形的周长和面积(均保留两位小数)。
样例输入 Sample Input
4 0 0 1 0 0 1 1 1
样例输出 Sample Output
4.00 1.00
时间限制 Time Limitation
各个测试点1s
注释 Hint
来源 Source
Alphonse.Elric
program p1233; uses math; Var a,b:array[0..20] of real; n,i,j,now,mini,maxi,top1,top2:longint; v,d:array[0..20] of boolean; q1,q2,pre:array[0..20] of longint; mincos,maxcos,sum,maxdt:real; Procedure fopen; begin assign(input,'p1233.in'); assign(output,'p1233.out'); reset(input); rewrite(output); end; Procedure fclose; begin close(input); close(output); end; Function Cos(x,y:real):real; begin exit(x/sqrt(x*x+y*y)); end; Procedure swap(var a,b:real); var y:real; begin y:=a; a:=b; b:=y; end; Function dt(x1,y1,x2,y2:real):real; begin exit(sqrt( sqr(x1-x2)+ sqr(y1-y2))); end; Function size(x1,y1,x2,y2:real):real; begin exit((x1*y2-x2*y1)/2); end; Function inline(x,y,x1,y1,x2,y2:real):boolean; begin if (x2=x1) then if (x=x1) and (y<max(y1,y2)) and (y>min(y1,y2)) then exit(true) else exit(false); if ((x=x1) or (x=x2)) then exit(false); if ((y-y1)/(x-x1)=(y-y2)/(x-x2)) and (y<max(y1,y2)) and (y>min(y1,y2)) then exit(true) else exit(false); end; begin //a=(1,0) b=(x,y) //cos<a,b> a在b的右侧 =x/|b| fopen; readln(n); for i:=1 to n do begin readln(a[i],b[i]); writeln(stderr,a[i],' ',b[i]); end; for i:=1 to n do for j:=i+1 to n do if (b[i]>b[j]) or ((b[i]=b[j]) and (a[i]>a[j])) then begin swap(a[i],a[j]); swap(b[i],b[j]); end; now:=1; top1:=1; q1[1]:=1; fillchar(v,sizeof(v),false); v[1]:=true; while now<n do begin maxdt:=0; maxcos:=-maxlongint; maxi:=0; for i:=now+1 to n do if not v[i] and ((cos(a[i]-a[now],b[i]-b[now])>maxcos) or ((cos(a[i]-a[now],b[i]-b[now])=maxcos) and (dt(a[i],b[i],a[now],b[now])>maxdt))) then begin maxcos:=cos(a[i]-a[now],b[i]-b[now]); maxi:=i; maxdt:=dt(a[i],b[i],a[now],b[now]); end; pre[maxi]:=now; v[maxi]:=true; inc(top1); q1[top1]:=maxi; now:=maxi; end; v[1]:=false; top2:=1; q2[1]:=n; now:=n; while now<>1 do begin maxdt:=0; mincos:=maxlongint; mini:=0; for i:=1 to now-1 do if not v[i] and ((cos(a[i]-a[now],b[i]-b[now])<mincos) or ((cos(a[i]-a[now],b[i]-b[now])=mincos) and (dt(a[i],b[i],a[now],b[now])>maxdt))) then begin mincos:=cos(a[i]-a[now],b[i]-b[now]); mini:=i; maxdt:=dt(a[i],b[i],a[now],b[now]); end; v[mini]:=true; inc(top2); q2[top2]:=mini; now:=mini; end; if q2[top2]=0 then dec(top2); sum:=0; for i:=1 to top1-1 do sum:=sum+dt(a[q1[i]],b[q1[i]],a[q1[i+1]],b[q1[i+1]]); for i:=1 to top2-1 do if pre[q2[i]]<>q2[i+1] then sum:=sum+dt(a[q2[i]],b[q2[i]],a[q2[i+1]],b[q2[i+1]]); writeln(sum:0:2); sum:=0; for i:=1 to top1-1 do sum:=sum+size(a[q1[i]],b[q1[i]],a[q1[i+1]],b[q1[i+1]]); for i:=1 to top2-1 do sum:=sum+size(a[q2[i]],b[q2[i]],a[q2[i+1]],b[q2[i+1]]); writeln(abs(sum):0:2); fclose; end.