Regular Polygon

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

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

The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest

 解题报告:这道题的题意就是在多边形的内部有一个点,点到达各个顶点的距离已知,求有这样的正多边形吗;思路,是把多边形分成N个三角形,多边形的边长一定满足三角形定理,min(两边之和)> 正多边形的边长> max(两边之差);在利用二分法枚举正多边形的边,直到枚举的便满足内角和为360即可,利用余弦定理求角的大小:cosA = (a* a + b * b - c * c) / 2 * a * b;

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const double PI = acos(-1.0);
const int MAX = 105;
const double eps = 1e-8;
double edge[MAX];
int T, N;
int main()
{
    int i, flag, k;
    double min, max, ans, radian;
    scanf("%d", &T);
    for (k = 1; k <= T; ++k)
    {
        memset(edge, 0, sizeof(edge));
        scanf("%d", &N);
        for (i = 0; i < N; ++i)
        {
            scanf("%lf", &edge[i]);
        }
        edge[N] = edge[0];
        max = 999999999;
        min = -20;
        double temp;
        for (i = 1; i <= N; ++i)
        {
            temp = edge[i] + edge[i - 1];
            //利用了三角形定理,两边之和大于第三边,两边之差小于第三边
            if (max > temp)//找到两边相加的最小
            {
                max = temp;
            }
            temp = fabs(edge[i] - edge[i - 1]);
            if (min < temp)//找到两边相减的最大
            {
                min = temp;
            }
        }
        double mid;
        flag = 0;
        while (max - min > eps)//利用二分法,枚举
        {
            mid = (max + min) / 2.0;
            radian = 0;//弧度
            for (i = 1; i <= N; ++i)
            {
                //利用余弦定理求弧度
                radian += acos((edge[i] * edge[i] + edge[i - 1] * edge[i - 1] - mid * mid) / (2.0 * edge[i] * edge[i - 1]));
            }
            if (fabs(radian - 2.0 * PI) < eps)//存在的时候
            {
                flag = 1;
                ans = mid;
                break;
            }
            else if (radian - 2 * PI > eps)//枚举的边大的
            {
                max = mid;
            }
            else//枚举的边小的时候
            {
                min = mid;
            }
        }
        printf("Case %d: ", k);
        if (flag)
        {
            printf("%.3lf\n", ans);
        }
        else
        {
            printf("impossible\n");
        }
    }
    return 0;
}
posted on 2012-04-06 21:23  Stephen Li  阅读(203)  评论(0编辑  收藏  举报