HDU 4033【数学几何余弦定理+二分求解方程】

题目:Regular Polygon

题意:

给一个正N边形内一点到各顶点的距离,求正N边形的边长。

解题思路:

听了题意后,马上想到的是二分答案,然后想到是根据面积相等构造等式,于是杯具了,直接导成都无望入线T_T,原因是根据面积相等构造的函数单调性难以判断,很麻烦。赛后一天cxyue跟我说根据内角度之和为360度就很容易二分了,原因是当边长与内角大小成正比,无疑是单调关系。但是提交总是WA,错误出在精度上,XX**,处理这些精度问题最讨厌了。精度调到1e-9TLE,调到1e-7WA,只有1e-8AC,妹!

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <string>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <map>
8 #include <cmath>
9
10 using namespace std;
11
12 const int MAX = 100 + 10;
13 const double INF = 10000000.0f;
14 const double PI = acos(-1.0);
15 int N;
16 double Edge[MAX];
17 void setRange(double& min, double& max)
18 {
19 Edge[N + 1] = Edge[1];
20 min = -1.0, max = INF;
21 for(int i = 1; i <= N; ++i)
22 {
23 if(fabs(Edge[i] - Edge[i + 1]) > min)
24 min = fabs(Edge[i] - Edge[i + 1]);
25 if(Edge[i] + Edge[i + 1] < max)
26 max = Edge[i] + Edge[i + 1];
27 }
28 }
29
30 double getArc(double a, double b, double c)
31 {
32 return acos((b * b + c * c - a * a) / (2.0 * b * c));
33 }
34
35 double func(double edge)
36 {
37 double angle = 0.0;
38 for(int i = 1; i <= N; ++i)
39 angle += getArc(edge, Edge[i], Edge[i + 1]);
40 return angle - PI * 2;
41 }
42 double solve(double left, double right)
43 {
44 double mid, funcM, funcL, funcR;
45 while(left < right)
46 {
47 mid = (right + left) / 2.0;
48 funcM = func(mid);
49 funcL = func(left);
50 funcR = func(right);
51 if(fabs(funcM) < 1e-8)
52 return mid;
53 if(funcM * funcL < 0)
54 right = mid;
55 else if(funcM * funcR < 0)
56 left = mid;
57 else
58 return -1.0;
59 }
60 }
61 int main()
62 {
63 freopen("in.txt","r",stdin);
64 int T;
65 scanf("%d", &T);
66 for(int t = 1; t <= T; ++t)
67 {
68 scanf("%d", &N);
69 for(int i = 1; i <= N; ++i)
70 scanf("%lf", &Edge[i]);
71 double min = -1.0, max = INF;
72 setRange(min, max);
73 double ans = solve(min + 1e-8, max - 1e-8);
74 printf("Case %d: ", t);
75 if(min < max && ans != -1.0)
76 printf("%.3f\n", ans);
77 else
78 printf("impossible\n");
79 }
80 return 0;
81 }

你可能感兴趣的:(HDU)