终于有题我过了T T。。
刚开始JC看错题了,以为是到各边的距离,然后觉得蛮水的,直接以0 0 为内点,旋转后求垂线围成的多边形是否是正多边形即可。
后来一看是到各顶点的距离。想了一会儿。
后来用余弦定理,二分边长(边长和反余弦是单调的)判断所有构成三角形的顶角和是否为2*pi即可。
构不成三角形的话直接判断即可。注意二分最后相等也需要判的,但是一直相等找不到结果的话就要跳出了。1Y~
精度开的1e-8,测试了下,1e-6也没问题。
感谢xymscau同学的检查,代码已经改过。二分边长后需要判定角度是否为多边形的角度,否则会出现菱形的情况,比如下组数据。代码已更正在HDU依然能AC,显然数据弱了,估计标程也没考虑这个情况。。。但是只有精度开到1e-6能过,其他均不行,无语。。
4
2 1.414 4 1.414
应该输出impossible,即使构成边长和菱形长度相同的正方形,但是不存在一个这样的点满足上述边长。
#include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string.h> #include <string> #include <algorithm> #define MID(x,y) ( ( x + y ) >> 1 ) #define L(x) ( x << 1 ) #define R(x) ( x << 1 | 1 ) #define FOR(i,s,t) for(int i=s; i<t; i++) #define BUG puts("here!!!") #define STOP system("pause") #define file_r(x) freopen("x", "r", stdin) #define file_w(x) freopen("x", "w", stdout) using namespace std; const int MAX = 110; const double pi = acos(-1.0); const double inf = 20000; double len[MAX]; const double eps = 1e-6; bool dy(double x,double y) { return x > y + eps;} // x > y bool xy(double x,double y) { return x < y - eps;} // x < y bool dyd(double x,double y) { return x > y - eps;} // x >= y bool xyd(double x,double y) { return x < y + eps;} // x <= y bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y double ang_cal(double a, double b, double c) { return acos((a*a + b*b - c*c)/(2*a*b)); } int solve(int n, double x) { double ang = 0; FOR(i, 0, n) { if( dyd(x, len[i] + len[i+1]) ) return 1; // 边长过大构不成三角形 if( xyd(x, fabs(len[i] - len[i+1])) ) return -1;//边长过小构不成三角形 double a = ang_cal(len[i], len[i+1], x); ang += a; } if( dy(ang, 2*pi) ) return 1; // 角度大,也就是x过大 if( xy(ang, 2*pi) ) return -1; // 角度小,也就是x过小 if( dd(ang, 2*pi) ) return 0; } bool check(int n, double ang, double x) { double a1 = ang_cal(len[1], x, len[0]); double a2 = ang_cal(len[1], x, len[2]); return dd(a1+a2, ang); } int main() { int ncases, n, ind = 1; scanf("%d", &ncases); while( ncases-- ) { scanf("%d", &n); FOR(i, 0, n) scanf("%lf", &len[i]); len[n] = len[0]; double begin = 0, end = inf, mid; bool f = false; int cnt = 0; while( xyd(begin, end) ) { if( dd(begin, end) ) cnt++; if( cnt == 2 ) break; // 避免找不到死循环 mid = (begin + end)/2; int ans = solve(n, mid); if( ans == 0 ) { f = true; break; } if( ans > 0 ) end = mid; else begin = mid; } printf("Case %d: ",ind++); if( f ) { double ang = (n-2)*pi/n; if( !check(n, ang, mid) ) // 检测角度是否为正多边形的角度 { printf("impossible\n"); continue; } printf("%.3lf\n", mid); } else printf("impossible\n"); } return 0; }