大致题意:
给出n个圆和m个三角形,求最小的的,能将所有图形覆盖的图形的周长。
正解为求所有三角形顶点与圆的切点以及圆和圆的切点构造凸包,再求路径。
因为要求结果误差<=1e-3 所以 我们可以在每个圆上,将圆分为1000(或更多)等分,得到每个圆上有1000个点,把这些点和三角形的顶点构造凸包,为减小误差,圆上两点的距离依然为圆弧的长度。这样累加边即可得答案。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<set> 7 #include<map> 8 #include<stack> 9 #include<time.h> 10 #include<cstdlib> 11 #include<cmath> 12 #include<list> 13 using namespace std; 14 #define MAXN 100100 15 #define eps 1e-9 16 #define For(i,a,b) for(int i=a;i<=b;i++) 17 #define Fore(i,a,b) for(int i=a;i>=b;i--) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 #define mkp make_pair 21 #define pb push_back 22 #define cr clear() 23 #define sz size() 24 #define met(a,b) memset(a,b,sizeof(a)) 25 #define iossy ios::sync_with_stdio(false) 26 #define fre freopen 27 #define pi acos(-1.0) 28 #define inf 1e6+7 29 #define Vector Point 30 const int Mod=1e9+7; 31 typedef unsigned long long ull; 32 typedef long long ll; 33 int dcmp(double x){ 34 if(fabs(x)<=eps) return 0; 35 return x<0?-1:1; 36 } 37 struct Point{ 38 double x,y; 39 int id; 40 Point(double x=0,double y=0,int id=-1):x(x),y(y),id(id) {} 41 bool operator < (const Point &a)const{ 42 if(x==a.x) return y<a.y; 43 return x<a.x; 44 } 45 Point operator - (const Point &a)const{ 46 return Point(x-a.x,y-a.y); 47 } 48 Point operator + (const Point &a)const{ 49 return Point(x+a.x,y+a.y); 50 } 51 Point operator * (const double &a)const{ 52 return Point(x*a,y*a); 53 } 54 Point operator / (const double &a)const{ 55 return Point(x/a,y/a); 56 } 57 void read(){ 58 scanf("%lf%lf",&x,&y); 59 } 60 void out(){ 61 cout<<"debug: "<<x<<" "<<y<<endl; 62 } 63 bool operator == (const Point &a)const{ 64 return dcmp(x-a.x)==0 && dcmp(y-a.y)==0; 65 } 66 }; 67 double Dot(Vector a,Vector b) { 68 return a.x*b.x+a.y*b.y; 69 } 70 double dis(Vector a) { 71 return sqrt(Dot(a,a)); 72 } 73 double Cross(Point a,Point b){ 74 return a.x*b.y-a.y*b.x; 75 } 76 int ConvexHull(Point *p,int n,Point *ch){ 77 int m=0; 78 For(i,0,n-1) { 79 while(m>1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; 80 ch[m++]=p[i]; 81 } 82 int k=m; 83 Fore(i,n-2,0){ 84 while(m>k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; 85 ch[m++]=p[i]; 86 } 87 if(n>1) m--; 88 return m; 89 } 90 void Swap(int &p1,int &p2){ 91 p1^=p2; 92 p2^=p1; 93 p1^=p2; 94 } 95 int n,m; 96 Point p[1000005]; 97 Point ch[1000005]; 98 Point cp[105]; 99 double r[105]; 100 void solve(){ 101 int rt=0; 102 For(i,0,n-1) cp[i].read(),scanf("%lf",&r[i]); 103 For(i,0,m-1) p[rt].id=n,p[rt++].read(),p[rt].id=n,p[rt++].read(),p[rt].id=n,p[rt++].read(); 104 For(i,0,n-1) { 105 For(j,0,999){ 106 double ang=2*j*pi*1.0/1000; 107 p[rt++]=Point(cp[i].x+r[i]*cos(ang),cp[i].y+r[i]*sin(ang),i); 108 } 109 } 110 sort(p,p+rt); 111 m=ConvexHull(p,rt,ch); 112 double ans=0; 113 For(i,0,m-1) { 114 if(ch[i].id==ch[(i+1)%m].id && ch[i].id!=n) { 115 ans+=pi*2*r[ch[i].id]/1000; 116 } 117 else ans+=dis(ch[i]-ch[(i+1)%m]); 118 } 119 printf("%.5lf\n",ans); 120 } 121 int main(){ 122 // fre("in.txt","r",stdin); 123 int t=0; 124 while(~scanf("%d%d",&n,&m)) solve(); 125 return 0; 126 }