• hdu 4033 Regular Polygon


    http://acm.hdu.edu.cn/showproblem.php?pid=4033

      这道题需要二分法求正多边形边长。

      题目给出正多边形内的一点与各个顶点间的连线线段长度,要求求出正多边形的边长,如果不存在这样的正多边形就输出impossible。

      由题目可以知道边长不会超过17320,所以就假设边长在(0, 20000)之间。然后,构造出计算当前状态的函数,再借助二分法来找到满足要求的点。这题的精度要求是精确到小数点后3位,不过要ac就必须将精度调至1e-6。计算当前状态的函数是要计算当边长为某个值的时候,所有相邻两条线的夹角和是否为2π。如果大于2π就缩小边长,否则就增大边长。

     

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <cstdlib>
     5 
     6 const int maxn = 101;
     7 const double pi = acos(-1.0);
     8 const double eps = 1e-6;
     9 double len[maxn];
    10 
    11 double cal(int n, double side){ // 二分收敛方向判定函数
    12     double tmp = side * side;
    13 
    14     if (side > len[0] + len[n - 1]) return 4 * pi;
    15     if (side < fabs(len[0] - len[n - 1])) return 0.0;
    16 
    17     double sum = acos((len[0] * len[0] + len[n - 1] * len[n - 1] - tmp) / (2 * len[0] * len[n - 1]));
    18 
    19     for (int i = 0; i < n - 1; i++){
    20         if (side > len[i] + len[i + 1]) return 4 * pi;
    21         if (side < fabs(len[i] - len[i + 1])) return 0.0;
    22         sum += acos((len[i] * len[i] + len[i + 1] * len[i + 1] - tmp) / (2 * len[i] * len[i + 1]));
    23     }
    24 
    25     return sum;
    26 }
    27 
    28 double bs(int n){ // 二分法找出满足要求的边长
    29     double h = 0.0;
    30     double t = 20000.0;
    31     double m, res;
    32 
    33     while (fabs(h - t) > eps){
    34         m = (h + t) / 2.0;
    35         res = cal(n, m);
    36         if (res > 2.0 * pi) t = m;
    37         else h = m;
    38     }
    39     if (fabs(cal(n, m) - 2 * pi) < 1e-4) return m; // 如果边长存在,则返回边长
    40     else return 1e301; // 否则返回正无穷
    41 }
    42 
    43 bool deal(int n, double &ans){
    44     ans = bs(n);
    45     if (ans > 1e300) return false;
    46 /**下面这部分原打算是判断多边形是否严格满足要求,不过发现加上去以后就不能ac了。我觉得是hdu将菱形或其它的伪正多边形当作是正多边形来给出边长了**/
    47 /*
    48     if (n <= 3) return true;
    49     double arc = 2.0 * pi / n;
    50     double l = ans * 2.0 * cos(arc / 2);
    51     double ang_a, ang_b ,ang_c;
    52     for (int i = 0; i < n - 2; i++){
    53         ang_a = acos((ans * ans - len[i] * len[i] - len[i + 1] * len[i + 1]) / (2 * len[i] * len[i + 1]));
    54         ang_b = acos((ans * ans - len[i + 2] * len[i + 2] - len[i + 1] * len[i + 1]) / (2 * len[i + 2] * len[i + 1]));
    55         ang_c = acos((l * l - len[i] * len[i] - len[i + 2] * len[i + 2]) / (2 * len[i] * len[i + 2]));
    56         if (fabs(ang_c - ang_b - ang_a) > 1e-4) return false;
    57     }
    58 */
    59     return true;
    60 }
    61 
    62 int main(){
    63 #ifndef ONLINE_JUDGE
    64     freopen("in", "r", stdin);
    65 #endif
    66     int T, n;
    67     double ans;
    68 
    69     scanf("%d", &T);
    70     for (int i = 1; i <= T; i++){
    71         scanf("%d", &n);
    72         for (int j = 0; j < n; j++){
    73             scanf("%lf", &len[j]);
    74         }
    75         printf("Case %d: ", i);
    76         if (deal(n, ans)){
    77             printf("%.3f\n", ans);
    78         }
    79         else{
    80             printf("impossible\n");
    81         }
    82     }
    83 
    84     return 0;
    85 }

    ——written by Lyon

     

  • 相关阅读:
    数值的扩展
    字符串的扩展
    变量的解构赋值整理
    let和const命令整理
    解析vue2.0中render:h=>h(App)的具体意思
    菜单栏的显示与隐藏
    vue的事件绑定
    CSS3实现3D地球自转行星公转
    MongoDB命令的简单操作(一)
    canvas扇形进度圈动态加载
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4033_Lyon.html
Copyright © 2020-2023  润新知