Gym-101158J Cover the Polygon with Your Disk 计算几何 求动圆与多边形最大面积交

题面

题意:给出小于10个点形成的凸多边形 和一个半径为r 可以移动的圆 求圆心在何处的面积交最大,面积为多少

题解:三分套三分求出圆心位置,再用圆与多边形面积求交

  1 #include<bits/stdc++.h>
  2 #define inf 1000000000000
  3 #define M 100009
  4 #define eps 1e-12
  5 #define PI acos(-1.0)
  6 using namespace std;
  7 struct node
  8 {
  9     double x,y;
 10     node(){}
 11     node(double xx,double yy)
 12     {
 13         x=xx;
 14         y=yy;
 15     }
 16     node operator -(node s)
 17     {
 18         return node(x-s.x,y-s.y);
 19     }
 20     node operator +(node s)
 21     {
 22         return node(x+s.x,y+s.y);
 23     }
 24     double operator *(node s)
 25     {
 26         return x*s.x+y*s.y;
 27     }
 28     double operator ^(node s)
 29     {
 30         return x*s.y-y*s.x;
 31     }
 32 }p[M],a[M];
 33 double max(double a,double b)
 34 {
 35     return a>b?a:b;
 36 }
 37 double min(double a,double b)
 38 {
 39     return a<b?a:b;
 40 }
 41 double len(node a)
 42 {
 43     return sqrt(a*a);
 44 }
 45 double dis(node a,node b)//两点之间的距离
 46 {
 47     return len(b-a);
 48 }
 49 double cross(node a,node b,node c)//叉乘
 50 {
 51     return (b-a)^(c-a);
 52 }
 53 double dot(node a,node b,node c)//点乘 
 54 {
 55     return (b-a)*(c-a);
 56 }
 57 int judge(node a,node b,node c)//判断c是否在ab线段上(前提是c在直线ab上)
 58 {
 59     if(c.x>=min(a.x,b.x)
 60        &&c.x<=max(a.x,b.x)
 61        &&c.y>=min(a.y,b.y)
 62        &&c.y<=max(a.y,b.y))
 63         return 1;
 64     return 0;
 65 }
 66 double area(node b,node c,double r)
 67 {
 68     node a(0.0,0.0);
 69     if (dis(b,c)<eps) return 0.0;
 70     double h=fabs(cross(a,b,c))/dis(b,c);
 71     if(dis(a,b)>r-eps&&dis(a,c)>r-eps)//两个端点都在圆的外面则分为两种情况
 72     {
 73         double angle=acos(dot(a,b,c)/dis(a,b)/dis(a,c));
 74         if(h>r-eps)
 75         {
 76             return 0.5*r*r*angle;
 77         }
 78         else if(dot(b,a,c)>0&&dot(c,a,b)>0)
 79         {
 80             double angle1=2*acos(h/r);
 81             return 0.5*r*r*fabs(angle-angle1)+0.5*r*r*sin(angle1);
 82         }
 83         else
 84         {
 85             return 0.5*r*r*angle;
 86         }
 87     }
 88     else if(dis(a,b)<r+eps&&dis(a,c)<r+eps)//两个端点都在圆内的情况
 89     {
 90         return 0.5*fabs(cross(a,b,c));
 91     }
 92     else//一个端点在圆上一个端点在圆内的情况
 93     {
 94         if(dis(a,b)>dis(a,c))//默认b在圆内
 95         {
 96             swap(b,c);
 97         }
 98         if(fabs(dis(a,b))<eps)//ab距离为0直接返回0
 99         {
100             return 0.0;
101         }
102         if(dot(b,a,c)<eps)
103         {
104             double angle1=acos(h/dis(a,b));
105             double angle2=acos(h/r)-angle1;
106             double angle3=acos(h/dis(a,c))-acos(h/r);
107             return 0.5*dis(a,b)*r*sin(angle2)+0.5*r*r*angle3;
108  
109         }
110         else
111         {
112             double angle1=acos(h/dis(a,b));
113             double angle2=acos(h/r);
114             double angle3=acos(h/dis(a,c))-angle2;
115             return 0.5*r*dis(a,b)*sin(angle1+angle2)+0.5*r*r*angle3;
116         }
117     }
118 }
119 int n;
120 double x,y,h,x1,yy,R;
121 double gets(node O)//求圆与多边形面积并 
122 {
123     for (int i=1;i<=n+1;i++) p[i]=a[i];
124       for(int i=1;i<=n+1;i++) p[i]=p[i]-O;
125     O=node(0,0);
126     double sum=0;
127     for(int i=1;i<=n;i++)
128     {
129         int j=i+1;
130         double s=area(p[i],p[j],R);
131         if(cross(O,p[i],p[j])>0) sum+=s; else sum-=s;
132     }    
133     return fabs(sum);
134 }
135 int dcmp(double x)
136 {
137     if(x > eps) return 1;
138     return x < -eps ? -1 : 0;
139 }
140 double calc(double x)
141 {
142     double l=1000000,r=-100000,m1,m2,f1=0,f2=0;
143     for (int i=1;i<=n;i++)
144     {
145         if (dcmp((a[i].x-x) * (a[i+1].x-x))<=0)
146         {
147             node tmp;
148             tmp.x=a[i].x+(a[i+1].x-a[i].x)/(a[i+1].x-a[i].x)*(x-a[i].x);
149             tmp.y=a[i].y+(a[i+1].y-a[i].y)/(a[i+1].x-a[i].x)*(x-a[i].x);
150             l=min(l,tmp.y);
151             r=max(r,tmp.y);
152         }
153     }
154     while (l+eps<r)
155     {
156         m1=(l+l+r)/3.0;     
157         node bom=node(x,m1);
158         f1=gets(bom);
159         m2=(l+r+r)/3.0;        
160         bom=node(x,m2); 
161         f2=gets(bom);
162         if (f1>f2) r=m2;else l=m1;
163     }
164     return f1;
165 }
166 int main()
167 {    
168     scanf("%d%lf",&n,&R);
169     double l=1000,r=-1000,m1,m2,f1,f2;
170     for(int i=1;i<=n;i++) 
171     {
172         scanf("%lf%lf",&a[i].x,&a[i].y);
173         l=min(l,a[i].x);
174         r=max(r,a[i].x);
175     }
176     a[n+1]=a[1];
177     while (l+eps<r)
178     {
179         m1=(l+l+r)/3.0;f1=calc(m1);
180         m2=(l+r+r)/3.0;f2=calc(m2);
181         if (f1>f2) r=m2;else l=m1;
182     }
183     printf("%.6lf
",f1);
184     return 0;
185 }
原文地址:https://www.cnblogs.com/qywhy/p/9772559.html