博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
codeforces 1C(几何题)
阅读量:7246 次
发布时间:2019-06-29

本文共 4744 字,大约阅读时间需要 15 分钟。

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

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

  其中会遇到的问题就是怎么求几个带小数部分的数的最大公约数了。其实原理很简单,就是跟整数求最大公约数一样,辗转相除,用到函数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

转载于:https://www.cnblogs.com/LyonLys/archive/2012/05/15/cf_1C_Lyon.html

你可能感兴趣的文章
如何使用VC++遍历某一个目录下的全部文件
查看>>
高德地图关键字搜索
查看>>
什么是Docker?为什么要使用Docker【转】
查看>>
Unix-Linux 编程实践教程 第五章 小结
查看>>
asp.net 界面中应用ajax返回值
查看>>
MySQL数据导入ElasticSearch
查看>>
idea同时部署两个项目时启动报错
查看>>
从一道面试题来认识java类加载时机与过程
查看>>
读Zepto源码之属性操作
查看>>
php 源码编译安装
查看>>
java值传递
查看>>
解释Eclipse下Tomcat项目部署路径问题(.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps)...
查看>>
40个Java多线程问题总结
查看>>
DBImport v3.5 中文版发布:数据库定时同步及文档生成工具(IT人员必备)
查看>>
020-添加用户
查看>>
023-手动增加swap分区
查看>>
20.27 分发系统介绍
查看>>
Java进阶(一)使用new Date()和System.currentTimeMillis()获取当前时间戳
查看>>
推荐引擎
查看>>
Java字符串常亮池
查看>>