• codeforces 1C(几何题)


    http://codeforces.com/problemset/problem/1/C

      这是一道几何计算题。题目目的是:给出在一个正多边形上的三点,要求你求出这个正多边形最小的面积是多少。因为一个正多边形有且仅有一个外接圆,而且正多边形的所有点都在这个圆上,因此这个正多边形的半径是固定的,所以,如果希望这个正多边形的面积尽可能小,正多边形的边数就必须尽可能少。

      因此,题目转化为求正多边形的最少边数。这时,常规的做法是先求出外接圆的圆心,然后借助圆心和三个点得连线,将圆划分成三份,然后求三个圆心角的最大公约数。这个最大公约数就是圆等分切割后的每一份最大的圆心角,从而求出这个正多边形的最少边数。

      其中会遇到的问题就是怎么求几个带小数部分的数的最大公约数了。其实原理很简单,就是跟整数求最大公约数一样,辗转相除,用到函数fmod,但是其中小数部分精度的处理则需要特别关注的。由于题目要求的的最大边数只有100条,因此精度定位只需要到0.01,如果精度太高,对于这题来说,是百害而无一利的。因为高的精度只会导致求gcd后的结果过于精确,计算得出的边数可能会增加,因此,这题的精度只需要1e-2。

      然后就是代码:

    View Code
      1 #include "cstdio"
      2 #include "cstdlib"
      3 #include "cstring"
      4 #include "cmath"
      5 #include "cctype"
      6 #include "vector"
      7 #include "set"
      8 #include "map"
      9 #include "string"
     10 #include "algorithm"
     11 #include "stack"
     12 #include "queue"
     13 
     14 #define INF 0x7fffffff
     15 #define reset(a) memset(a, 0, sizeof(a))
     16 #define copy(a, b) memcpy(a, b, sizeof(b))
     17 #define FMAX (1E300)
     18 #define MAX 1000000000
     19 #define feq(a, b) (fabs((a)-(b))<1E-2)
     20 #define flq(a, b) ((a)<(b)||feq(a, b))
     21 #define MAXN 10005
     22 #define BASE 137
     23 #define PASS puts("pass")
     24 #define filein freopen("test.in", "r", stdin)
     25 #define fileout freopen("test.out", "w", stdout)
     26 
     27 using namespace std;
     28 const double PI = acos(-1);
     29 
     30 struct Point{
     31     double x;
     32     double y;
     33 };
     34 
     35 void swap(double &a, double &b){
     36     double t;
     37     t = a;
     38     a = b;
     39     b = t;
     40 }
     41 
     42 bool find_center(Point *p, Point &c){
     43 //存在外接圆返回true,否则返回false
     44     double dx1 = p[1].x - p[0].x;
     45     double dy1 = p[1].y - p[0].y;
     46     double dx2 = p[2].x - p[0].x;
     47     double dy2 = p[2].y - p[0].y;
     48 
     49     if (feq(dx1 * dx2 + dy1 * dy2, 0)){
     50         c.x = (p[1].x + p[2].x) / 2;
     51         c.y = (p[1].y + p[2].y) / 2;
     52 
     53         return true;
     54     }
     55     if (feq(dx1 * dy2, dx2 * dy1))
     56         return false;
     57 
     58     double mx1 = (p[1].x + p[0].x) / 2;
     59     double my1 = (p[1].y + p[0].y) / 2;
     60     double mx2 = (p[2].x + p[0].x) / 2;
     61     double my2 = (p[2].y + p[0].y) / 2;
     62     double a1 = dx1, b1 = dy1, c1 = - mx1 * dx1 - my1 * dy1;
     63     double a2 = dx2, b2 = dy2, c2 = - mx2 * dx2 - my2 * dy2;
     64 
     65     c.x = (c1 * b2 - c2 * b1) / (a2 * b1 - a1 * b2);
     66     c.y = (c1 * a2 - c2 * a1) / (a1 * b2 - a2 * b1);
     67     /**
     68     printf("%.6f  %.6f\n", c.x, c.y);
     69     printf("a1  %.6f    b1  %.6f    c1  %.6f\n", a1, b1, c1);
     70     printf("a2  %.6f    b2  %.6f    c2  %.6f\n", a2, b2, c2);
     71     /**/
     72     return true;
     73 }
     74 
     75 double fgcd(double a, double b){
     76 //带小数的两个数求最大公约数
     77     if (feq(a, 0))
     78         return b;
     79     if (feq(b, 0))
     80         return a;
     81     return fgcd(b, fmod(a, b));
     82 }
     83 
     84 int main(){
     85     Point tri[4];
     86 
     87     //filein;
     88     //fileout;
     89     while (1){
     90         for (int i = 1; i <= 3; i++){
     91             if (!~scanf("%lf%lf", &tri[i].x, &tri[i].y))
     92                 return 0;
     93         }
     94         find_center(&tri[1], tri[0]);
     95         /**
     96         if (find_center(&tri[1], tri[0])){
     97             printf("Exist!\nx = %10.6f      y = %10.6f\n", tri[0].x, tri[0].y);
     98         }
     99         else printf("Not exist!\n");
    100         /**求出三角形三条边的长度**/
    101         double r = sqrt((tri[1].x - tri[0].x) * (tri[1].x - tri[0].x)
    102                         + (tri[1].y - tri[0].y) * (tri[1].y - tri[0].y));
    103         double l1 = sqrt((tri[2].x - tri[3].x) * (tri[2].x - tri[3].x)
    104                         + (tri[2].y - tri[3].y) * (tri[2].y - tri[3].y));
    105         double l2 = sqrt((tri[1].x - tri[3].x) * (tri[1].x - tri[3].x)
    106                         + (tri[1].y - tri[3].y) * (tri[1].y - tri[3].y));
    107         double l3 = sqrt((tri[1].x - tri[2].x) * (tri[1].x - tri[2].x)
    108                         + (tri[1].y - tri[2].y) * (tri[1].y - tri[2].y));
    109         /**对三条边的长度排序,从而得到最短的两条边**/
    110         if (l3 < l1){
    111             swap(l1, l3);
    112         }
    113         if (l3 < l2){
    114             swap(l2, l3);
    115         }
    116         //printf("\nl1 %.6f   l2 %.6f   l3 %.6f   r %.6f\n", l1, l2, l3, r);
    117         /**求出圆心角**/
    118         double angle1 = acos(1 - (l1 / r) * (l1 / r) / 2) * 180/ PI;
    119         double angle2 = acos(1 - (l2 / r) * (l2 / r) / 2) * 180 / PI;
    120         double angle3 = 360 - angle1 - angle2;
    121         double e = 360 / fgcd(angle1, fgcd(angle2, angle3));
    122 
    123         /**
    124         printf("a1 %.6f   a2 %.6f   a3 %.6f\n", angle1, angle2, angle3);
    125         printf("%.6f\n", fgcd(angle1, fgcd(angle2, angle3)));
    126         printf("%.6f\n", e);
    127         /**/
    128 
    129         double angle = 360 / e;
    130 
    131         printf("%.8f\n", sin(angle * PI / 180) * r * r * e / 2);
    132     }
    133 }

      作为一个ACMer,我觉得这些数学题的学习是十分必要的。

    ——written by Lyon

  • 相关阅读:
    搭建ARL资产安全灯塔
    免杀技术发展史
    米酷CMS 7.0.4代码审计
    腾讯安全实习 应用运维安全面试
    Docker部署CTF综合性靶场,定时刷新环境
    西湖论剑2020MISC-Yusa_yyds
    (转)马云炮轰银行监管的解读
    ATT&CK 实战
    Docker环境复现利用Redis未授权访问漏洞 >> 批量扫描检测利用
    修改CH340芯片信息
  • 原文地址:https://www.cnblogs.com/LyonLys/p/cf_1C_Lyon.html
Copyright © 2020-2023  润新知