大致题意:

  给出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 }
View Code