hdu 4033 Regular Polygon

来源:互联网 发布:电脑删除数据恢复 编辑:程序博客网 时间:2024/05/20 11:46

终于有题我过了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 == ydouble 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;elsebegin = 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);}elseprintf("impossible\n");}return 0;}