Building Fence hdu 凸包

来源:互联网 发布:淘宝外贸原单男装店铺 编辑:程序博客网 时间:2024/05/15 16:42

从技巧上来说,这种代码明显比,求圆切线来的简单的多,但是从精确角度,我其实是去取巧了,在精度上随着圆被分的越小份,精度越高,是否已经看出来,我只是将圆分成很多个点,平均份,但是当在计算时,一个圆内的点还是,用2*pi*R[b[i].id]/1000.0,之前我还是当成直线,但精度确失去了;   我这里份成了一千份,当然你可以不这么计算,那么你将要分成2000分,计算时间必然是增加的,我本来想分成10000份来着,结果超时了,还是老老实实分成一千分,在加一个2*pi*R[b[i].id]/1000.0让精度尽量正确;
#include <stdio.h>
#include <iostream>
#include  <cstring>
#include <algorithm>
#include <math.h>
using namespace std;
#define pi acos(-1.0)
#define esp 1e-10
//int dcmp(double x)//减少误差
//{
   // if(fabs(x)<=esp)
      //  return 0;
     //  if(x>0)
     //   return 1;
      //   return -1;


//}

struct point
{
    double x,y;
    int id;
    point(){}
     point(double x,double y,int i):x(x),y(y),id(i){}//方便构造
   // bool operator <(const struct point &tmp)const//排序,先X从小到大接着Y从小到大;
  // {
    //    if(dcmp(x-tmp.x)==0) return dcmp(y-tmp.y)<0;
   //     return dcmp(x-tmp.x)<0;
  // }
}a[105555],b[105555];
bool cmp(point l,point w)//事实上这种排序便够了,也是AC的但是精度上确实是不如的
{
    if(l.x==w.x)
        return  l.y<w.y;
    return l.x<w.x;
}
int p,R[1005];
double r;

double chaji(point a1,point a2,point a3)
{
    return (a2.x-a1.x)*(a3.y-a1.y)-(a2.y-a1.y)*(a3.x-a1.x);
}
double len_x(point a1,point a2)
{
     return sqrt((a1.x-a2.x)*(a1.x-a2.x)+(a1.y-a2.y)*(a1.y-a2.y));
}
void circle(int m)
{
    double x,y;
    scanf("%lf%lf%d",&x,&y,&R[m]);
    double x1,y1;
    for(int i=0;i<1000;i++)
    {
        double tmp = 2*pi*i/1000.0;
        x1=x+cos(tmp)*R[m];
        y1=y+sin(tmp)*R[m];
        a[p]=point(x1,y1,m);
        p++;
    }
}
int main()
{
    int n,i,j,m;
    double l,w,sum;
    while(~scanf("%d%d",&n,&m))
    {
        p=0;
        for(i=0;i<n;i++)
            circle(i);
        for(i=0;i<m;i++)
            for(j=0;j<3;j++)
            {
            scanf("%lf%lf",&a[p].x,&a[p].y);
            a[p].id=p++;
            }
            if(n==1&&m==0)
            {
                printf("%.10lf\n",2*pi*R[0]);
                continue;
            }
            sort(a,a+p,cmp);
      //  printf("%d\n",p);

      m=0;
      for(i=0;i<p;i++)
      {
          while(m>1&&chaji(b[m-2],a[i],b[m-1])>=0)  m--;//先找下凸包
          b[m++]=a[i];
      }
      int k=m;
      for(i=p-2;i>=0;i--)
      {
          while(k>m&&chaji(b[k-2],a[i],b[k-1])>=0)  k--;//再找上凸包
          b[k++]=a[i];
      }
      sum=0;
   //   printf("%lf %lf %lf %lf. ",b[0].x,b[0].y,b[1].x,b[1].y);

      for(i=0;i<k-1;i++)
      {
          if(b[i].id==b[i+1].id)
            sum+=2*pi*R[b[i].id]/1000.0;
          else
          sum+=len_x(b[i],b[i+1]);

// printf(" %lf ",sum);
          //if(i==20)
           // break;
      }
     // printf("%lf %lf\n",b[i].x,b[i].y);
     printf("%.10lf\n",sum);
    }
}

 

 

0 0
原创粉丝点击