【好题】思维+几何+弦的圆心角——ICPC GNYR 2019 E
/* 两个重要的结论: 1.将每条边强行移到圆上,如果多边形所有边的圆心角之和=2pi,那么圆心在多边形中;>2pi,那么圆半径太小;<2pi,圆半径太大 2.不管按什么顺序摆放边,都不影响多边形的对应其外接圆(如果有)的圆心角之和
给定多边形的各边边长,要求构造出一个多边形,使其所有点在外切圆上,且圆心在多边形内,半径<=120 首先是NO CIRCLE:所有边组不成三角形,即最长边>=其余边之和 然后是OUTSIDE:参考钝角三角形,以最长边为直径,如果其他边的圆心角之和<pi,说明圆心必定在多边形外面 然后是TOO BIG: 直接以120为半径,如果所有边圆心角之和==2pi,则符合 然后是二分求最小半径:所有边圆心角之和>2pi,那么半径要扩大,反之要收缩 */ #include<bits/stdc++.h> using namespace std; #define N 205 #define db double const db pi = acos(-1.0); const db eps = 1e-6; int sign(db x){ if(x>eps)return 1; if(x<-eps)return -1; return 0; } db sum,l[N]; int n; db calc(db r){// 以r为半径,把所有边当成弦,求所有弦对应的圆心角之和 if(sign(l[n]-2*r)>0)return -1; db res=0; for(int i=1;i<=n;i++) res+=asin(l[i]/(2.0*r)); return res*2.0; } int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>l[i]; sort(l+1,l+1+n); for(int i=1;i<n;i++)sum+=l[i]; if(sign(l[n]-sum)>=0){ puts("NO CIRCLE");return 0; } db sumang=calc(l[n]/2); if(sign(sumang-2*pi)<0){ puts("OUTSIDE");return 0; } sumang=calc(120.0); if(sumang==-1 || sign(sumang-2*pi)>0){ puts("TOO BIG");return 0; } db L=l[n]/2,R=120.0,mid,ans; for(int t=1;t<=50;t++){ mid=(L+R)/2; sumang=calc(mid); if(sumang==-1) L=mid; else if(sign(sumang-2*pi)>0) L=mid; else if(sign(sumang-2*pi)<0) R=mid; else ans=mid,R=mid; } printf("%.4lf\n",ans); }