hdu4033(计算几何)

Regular Polygon

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 2905    Accepted Submission(s): 884


Problem Description
In a 2_D plane, there is a point strictly in a regular polygon with N sides. If you are given the distances between it and N vertexes of the regular polygon, can you calculate the length of reguler polygon's side? The distance is defined as dist(A, B) = sqrt( (Ax-Bx)*(Ax-Bx) + (Ay-By)*(Ay-By) ). And the distances are given counterclockwise.
 

Input
First a integer T (T≤ 50), indicates the number of test cases. Every test case begins with a integer N (3 ≤ N ≤ 100), which is the number of regular polygon's sides. In the second line are N float numbers, indicate the distance between the point and N vertexes of the regular polygon. All the distances are between (0, 10000), not inclusive.
 

Output
For the ith case, output one line “Case k: ” at first. Then for every test case, if there is such a regular polygon exist, output the side's length rounded to three digits after the decimal point, otherwise output “impossible”.
 

Sample Input
  
  
2 3 3.0 4.0 5.0 3 1.0 2.0 3.0
 

Sample Output
  
  
Case 1: 6.766 Case 2: impossible
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   4039  4038  4034  4035  4032 
 
      本题给定正多边形内一点到各个顶点的距离,要求是否存在这样的多边形。
      本题的突破口是多边形为正多边形,几个边相等,对应的内角相等。我们可以二分枚举边长,只要同时满足下面的两个条件即可:
 
 1.构成三角形
 2.角度等于360.
      本题在卡精度,不知为什么一直WA。
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;

const double PI2=2*acos(-1.0);
const double eps=1e-8;
const int MAXN=100+10;
double Edg[MAXN];
int n;

double Angle(double a,double b,double c)
{
	return acos((a*a+b*b-c*c)/(2.0*a*b));
}

int IsPology(double len)
{
	double sumangle=0.0;
	for(int i=1;i<n+1;i++)
	{
		sumangle+=Angle(Edg[i],Edg[i-1],len);
	}
	if(fabs(sumangle-PI2)<=eps)
		return 0;
	else if(sumangle>PI2)
		return -1;
	return 1;
}

void Solve()
{
	double high,low,mid;
	Edg[n]=Edg[0];
	high=Edg[0]+Edg[1];
	low=fabs(Edg[0]-Edg[1]);
	for(int i=2;i<n+1;i++)
	{
		double tmp=Edg[i]+Edg[i-1];
		if(high<tmp)
			high=tmp;
		tmp=fabs(Edg[i]-Edg[i-1]);
		if(tmp>low)
			low=tmp;
	}
	bool flag=false;
	high-=eps;
	low+=eps;
	while(high>low+eps)
	{
		mid=(high+low)/2.0;
		int t=IsPology(mid);
		if(t==0)
		{
			flag=true;
			break;
		}
		else if(t==-1)
			high=mid;
		else low=mid;
	}
	if(flag)
		printf("%0.3lf\n",mid);
	else printf("impossible\n");
}

int main()
{
	int cas;
	int tag=1;
	scanf("%d",&cas);
	while(cas--)
	{
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%lf",&Edg[i]);
		printf("Case %d: ",tag++);
		Solve();
	}
	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值