题中给定某一点到N个点的距离,问这些点能否组成正多边形?
思路:选定两条边,通过二分法枚举某一条边的边长,算出该边长下对应的中心角,然后再依据此边计算出其余三角形对应的中心角,最后看总的角度是否为360度。
代码如下:
#include#include #include using namespace std; double e[200]; const double PI = 4 * atan( double( 1 ) ); int N; double istri( double a, double b, double c ) { if( c > a + b ) return 5; else if( c < fabs( a - b ) ) return -5; else return acos( ( a * a + b * b - c * c ) / ( 2 * a * b ) ); } double Acos( double a, double b, double c ) { return istri( a, b, c ); } double bs( double mid ) { double ans = 0; for( int i = 2; i <= N; ++i ) { double t = Acos( e[i], e[i-1], mid ); if( fabs( t ) == 5 ) // 如果mid的这个取值使得某些相邻的两条边不 return t; // 能够形成三角形,则及时退出 else ans += Acos( e[i], e[i-1], mid ); } return ans; // 最后返回总的角度大小 } double bsearch( double ss, double ee ) { double l = ss, r = ee, mid, sum_angle; while( r - l >= 1e-9 ) { mid = ( l + r ) / 2.0; double t = bs( mid ); // 计算出一部分的角度总和 if( fabs( t ) == 5 ) { if( t > 0 ) r = mid; else l = mid; } else { sum_angle = t + Acos( e[1] , e[N], mid ); if( sum_angle - 2 * PI > 1e-9 ) r = mid; else if( sum_angle - 2 * PI < -1e-9 ) l = mid; else return mid; } } return 0; } int main( ) { int T; scanf( "%d", &T ); for( int ca = 1; ca <= T; ++ca ) { scanf( "%d", &N ); for( int i = 1; i <= N; ++i ) { scanf( "%lf", &e[i] ); } // 接下来选择第N条边以及第1条边来二分答案 // 根据三角形中有 C < A+B && C > A-B; double ans = bsearch( fabs( e[N] - e[1] ), e[1] + e[N] ); printf( "Case %d: ", ca ); if( ans == 0 ) puts( "impossible" ); else printf( "%.3lf\n", ans ); } return 0; }