zoukankan      html  css  js  c++  java
  • 【凸包】含共线判定O(N^2)

    Vijos P1253

    @.@多边形面积

    From 路光

    描述 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.
    
  • 相关阅读:
    xshell常用命令
    linux传输文件命令: rz 和 sz
    使用openssh-clients的scp命令来传输文件
    RabbitMQ初学之二:直接发送消息到队列
    [App]华为P6设置与Xamarin Studio连通测试
    [Boost]图形处理库Boost::Polygon
    [App]Taste VS2015 && Android Studio
    [Linux&Vim]输入输出流
    [SSD大法好]神舟K480-I5-D3鸟枪换炮M6S
    [IoLanguage]Io Tutorial[转]
  • 原文地址:https://www.cnblogs.com/htfy/p/2770648.html
Copyright © 2011-2022 走看看