现在的位置: 首页 > 综合 > 正文

hdu 4033 Regular Polygon

2013年12月09日 ⁄ 综合 ⁄ 共 2169字 ⁄ 字号 评论关闭

终于有题我过了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;
}

抱歉!评论已关闭.