从技巧上来说,这种代码明显比,求圆切线来的简单的多,但是从精确角度,我其实是去取巧了,在精度上随着圆被分的越小份,精度越高,是否已经看出来,我只是将圆分成很多个点,平均份,但是当在计算时,一个圆内的点还是,用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);
}
}