Temple of Dune
memory limit: 65536KB time limit: 500MS
accept: 5 submit: 11
Description
The Archaeologists of the Current Millenium (ACM) now and then discover ancient artifacts located at the vertices of regular polygons. In general it is necessary to move one sand dune to uncover each artifact. After discovering three artifacts, the archaeologists wish to compute the minimum number of dunes that must be moved to uncover all of them.
Input
The first line of input contains a positive integer n, the number of test cases. Each test case consists of three pairs of real numbers giving the x and y coordinates of three vertices from a regular polygon.
Output
For each line of input, output a single integer stating the fewest vertices that such a polygon might have. You may assume that each input case gives three distinct vertices of a regular polygon with at most 200 vertices.
Sample Input
4
10.00000 0.00000 0.00000 -10.00000 -10.00000 0.00000
22.23086 0.42320 -4.87328 11.92822 1.76914 27.57680
156.71567 -13.63236 139.03195 -22.04236 137.96925 -11.70517
129.400249 -44.695226 122.278798 -53.696996 44.828427 -83.507917
Sample Output
4
6
23
100
Source
ZQUCPC个人赛4
Author
Waterloo local
题意:
给出一个三角形三个顶点的坐标,有一个正多边形使得这三个点都在该正多边形的边上,求满足条件的最少边的正多边形,输出边数。
提交次数:
1次AC
总耗时:
5小时以上
问题的分析与解题思路:
画出图形后不难判断,满足条件的正多边形正好与该三角形共外接圆,而三角形每条边对应的圆心角正好占了正多边形边对应的圆心角的n份,因此只要求出正多边形的圆心角,然后用二倍圆周率除以该圆心角即为边数。而正多边形的圆心角为三角形每个边对应的圆心角的最大公倍数。
出错的地方:
这个题花了我很长的时间思考,但一直没法得到答案,有几个地方是我失误的:
1. 求三角形圆心角(V1,V2,V3)时,因为画的是第一个测试例子的三角形,该三角形三个顶点刚好在坐标轴上,因此直接拿三角形的顶点来求圆心角。后来调试的时候才发现这里应该用三个顶点两两之间的向量来求。
2. 一开始我没想到求最大公约数,后来是在网上搜到的(PS:此题在网上很少有资料,而且那些所谓AC的代码都是有问题的)。我的想法是用让边数n从小自增,则正多边形的圆心角为s=pi*2/n,然后看能不能s被V1,V2,V3同时整除,但是因为求出的角度是浮点数,显然不能用取模,于是想到让s成倍增长,如果等于V1则同理求V2V3的,如果超过V1则跳过本次循环。但是在调试过程中发现s和V1,V2,V3是通过不同的方法求出的,肯定会存在误差,即即使本是相等的,但是会在小数点后某一位出现误差,而且误差的开始的位置是不相同的,即不能通过取小数点后的某几位来作为结果,因为取得多了可能有些例子就过不了了,取得少了又有一些例子过不了。这个问题纠结了我两三个小时一直无解,直到我上网搜索。
AC方法和数据结构:
先求处三角形对应外接圆的三个圆心角,利用数学公式可求得圆周角,然后根据同弧的圆心角为圆周角的两倍可求的圆心角,然后求这三个圆心角的最大公约数,最后两倍圆周率除以这个最大公约数即为所求。
公式为:cosV=A*B/(|A|*|B|),V为夹角,即为所求的圆心角,A B为向量;A=(x1-x2,y1-y2)B=(x3-x2,y3-y2) ; |A|=sqrt(xa*xa+ya*ya);
圆周率的求法有两种,一种是直接赋值,圆周率为3.1415926535897,另一种是用数学方法求的,圆周率等于-1的反余弦值,即pi=acos(-1);
AC代码:
算法复杂度分析:
时间复杂度是o(n)
总结:
这道题算法不难,但是需要一些技巧。利用了数学的一些常用几何公式,这些公式要牢记,然后还有一个是求三个浮点数的最大公约数,可以利用此题形成一个模版。思考问题的时候,如果在一个角度苦思不得其解时,不妨换个角度,往往能得到答案,但是如何换角度是个难题。
求三个浮点数的最大公约数(网上搜来的):
其中fmod(a,b);为求a对b的模,定义在<math.h>中,也可以自己写。
#include <math.h>
double fmod(double x, double y);
自己写的方法为:
double fmod(double x, double y)
{
return x-floor(x/y)*y;
}