HDU 2017 多校联合训练赛2 1011 6055 Regular polygon map&pair
2017-07-28 14:34
627 查看
Regular polygon
[align=center]Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)[/align]
[align=left]Problem Description[/align]
On a two-dimensional plane, give you n integer points. Your task is to figure out how many different regular polygon these points can make.
[align=left]Input[/align]
The input file consists of several test cases. Each case the first line is a numbers N (N <= 500). The next N lines ,each line contain two number Xi and Yi(-100 <= xi,yi <= 100), means the points’ position.(the data assures no two
points share the same position.)
[align=left]Output[/align]
For each case, output a number means how many different regular polygon these points can make.
[align=left]Sample Input[/align]
4
0 0
0 1
1 0
1 1
6
0 0
0 1
1 0
1 1
2 0
2 1
[align=left]Sample Output[/align]
1
2
[align=left]Source[/align]
2017 Multi-University Training Contest - Team 2
题目大意
在一个平面直角坐标系中,给出n个点,问这n个点能组成多少个正多边形。(注意:每个点的坐标都是整数)
题目解析
该题目的突破点在于一条性质:如果在平面直角坐标系中,每个点的坐标都是整数,那么这些点能组成的正多边形只能是正方形。(具体证明可参考杨景钦在2017的国家队论文)
在这里我们只是简单理解一下该性质。如果给每种正多边形做外接圆,我们会发现,正多边形的每个点都在它的外接圆上。现在,在坐标系中任意画一个圆,我们会发现,在圆上最多只能找到四个整数坐标点,并且一定是正方形的四个点。
现在,题目就简单了许多。我们只需要枚举任意两点,判断包含这两个点的正方形的另两个点的理论位置上,是否真正存在两个点,如果两个点都存在,那么answer++。注意,如果存在一个正方形,那么这个正方形的4条边上的两个点,都满足判断条件,所以answer++重复操作4次。
判断理论点的位置是否真正存在点,为了简化操作的时间复杂度,我们可以采用两种方法:1.引入vis[ ]数组,记录每个点是否出现过;2.使用STL中的map 和 pair,详情请参考代码。
方法二的好
9d9c
处是空间复杂度更低,对于更大的点的数据量的情况也可以应付;并且代码更简洁;
对于方法一,从代码上来讲,似乎更好理解,但是需要我们特别注意的问题是,数组越界。题目中,坐标的范围是[-100,100],然而我们的数组范围是从0开始的,这样就需要我们将所有的坐标加上100,并不影响后来的计算。另外构成正方形的另外两个理论点的坐标也要保证不能越界。
代码1
#include <cstdio> #include <iostream> #include <cstring> using namespace std; int n, ans; int x[505], y[505]; bool vis[205][205]; int main() { while (~scanf ("%d",&n)) { ans = 0; memset(vis, 0, sizeof(vis)); for (int i=0; i<n; ++i) { scanf ("%d %d",&x[i],&y[i]); x[i] += 100; y[i] += 100; vis[x[i]][y[i]] = 1; } for (int i=0; i<n; ++i) { for (int j=i+1; j<n; ++j) { int dx = y[j]-y[i]; int dy = x[i]-x[j]; if (x[i]+dx>=0 && x[i]+dx<=200 && y[i]+dy>=0 && y[i]+dy<=200 && x[j]+dx>=0 && x[j]+dx<=200 && y[j]+dy>=0 && y[j]+dy<=200) if (vis[x[i] + dx][y[i] + dy] && vis[x[j] + dx][y[j] + dy]) ans ++; if (x[i]-dx>=0 && x[i]-dx<=200 && y[i]-dy>=0 && y[i]-dy<=200 && x[j]-dx>=0 && x[j]-dx<=200 && y[j]-dy>=0 && y[j]-dy<=200) if (vis[x[i] - dx][y[i] - dy] && vis[x[j] - dx][y[j] - dy]) ans ++; } } printf ("%d\n",ans/4); } return 0; }
代码2
#include <cstdio> #include <iostream> #include <cstring> #include <utility>//pair #include <map> using namespace std; int n, ans; int x[505], y[505]; map < pair <int, int>, bool> M; int main() { while (~scanf ("%d",&n)) { ans = 0; M.clear(); for (int i=0; i<n; ++i) { scanf ("%d %d",&x[i],&y[i]); M[make_pair(x[i], y[i])] = 1; } for (int i=0; i<n; ++i) { for (int j=i+1; j<n; ++j) { int dx = y[j]-y[i]; int dy = x[i]-x[j]; if (M.count(make_pair(x[i] + dx, y[i] + dy)) && M.count(make_pair(x[j] + dx, y[j] + dy))) ans ++; if (M.count(make_pair(x[i] - dx, y[i] - dy)) && M.count(make_pair(x[j] - dx, y[j] - dy))) ans ++; } } printf ("%d\n",ans/4); } return 0; }
相关文章推荐
- 2017多校联合第二场 1011题 hdu 6055 Regular polygon 计算几何
- HDU 6055 (2017 多校训练赛2 1011)Regular polygon
- HDU-2017 多校训练赛2-1011-Regular polygon
- (2017多校训练第二场)HDU - 6055 & POJ - 2002 Regular polygon 哈希
- (2017多校2)1011/hdu-6055 Regular polygon(计算几何)
- HDU 2017 多校联合训练赛8 1011 6143 Killer Names 排列组合
- hdu 6055 : Regular polygon (2017 多校第二场 1011) 【计算几何】
- HDU 2017 多校联合训练赛2 1009 6053 TrickGCD 莫比乌斯函数
- HDU-2017 多校训练赛7-1011-Kolakoski
- HDU 2017 多校联合训练赛6 1008 6103 Kirinriki 优美的暴力
- HDU 2017 多校联合训练赛4 4003 6069 Counting Divisors 素数筛和素因数分解
- HDU 2017 多校联合训练赛7 1008 6127 Hard challenge (重载运算符)
- HDU-2017 多校训练赛8-1011-Killer Names
- hdu 5349 MZL's simple problem 2015多校联合训练赛#5 简单题
- 2017 多校训练第二场 HDU 6055 Regular polygon
- HDU 6043(2017 多校训练赛1 1011) KazaQ's Socks
- HDU 2017 多校联合训练赛7 1010 6129 Just do it 杨辉三角 组合数的奇偶判断
- HDU-2017 多校训练赛6-1011-Classes
- hdu 5352 MZL's City 2015多校联合训练赛#5 费用流
- HDU 6106 (2017 多校训练赛6 1011)Classes