Regular polygon
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
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.
Input
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.)
Output
For each case, output a number means how many different regular polygon these points can make.
Sample Input
4 0 0 0 1 1 0 1 1 6 0 0 0 1 1 0 1 1 2 0 2 1
Sample Output
1 2
Source
2017 Multi-University Training Contest - Team 2
题目大意
在一个平面直角坐标系中,给出n个点,问这n个点能组成多少个正多边形。(注意:每个点的坐标都是整数)
题目解析
该题目的突破点在于一条性质:如果在平面直角坐标系中,每个点的坐标都是整数,那么这些点能组成的正多边形只能是正方形。(具体证明可参考杨景钦在2017的国家队论文)
在这里我们只是简单理解一下该性质。如果给每种正多边形做外接圆,我们会发现,正多边形的每个点都在它的外接圆上。现在,在坐标系中任意画一个圆,我们会发现,在圆上最多只能找到四个整数坐标点,并且一定是正方形的四个点。
现在,题目就简单了许多。我们只需要枚举任意两点,判断包含这两个点的正方形的另两个点的理论位置上,是否真正存在两个点,如果两个点都存在,那么answer++。注意,如果存在一个正方形,那么这个正方形的4条边上的两个点,都满足判断条件,所以answer++重复操作4次。
判断理论点的位置是否真正存在点,为了简化操作的时间复杂度,我们可以采用两种方法:1.引入vis[ ]数组,记录每个点是否出现过;2.使用STL中的map 和 pair,详情请参考代码。
方法二的好处是空间复杂度更低,对于更大的点的数据量的情况也可以应付;并且代码更简洁;
对于方法一,从代码上来讲,似乎更好理解,但是需要我们特别注意的问题是,数组越界。题目中,坐标的范围是[-100,100],然而我们的数组范围是从0开始的,这样就需要我们将所有的坐标加上100,并不影响后来的计算。另外构成正方形的另外两个理论点的坐标也要保证不能越界。
代码1
代码2
题目大意
在一个平面直角坐标系中,给出n个点,问这n个点能组成多少个正多边形。(注意:每个点的坐标都是整数)
题目解析
该题目的突破点在于一条性质:如果在平面直角坐标系中,每个点的坐标都是整数,那么这些点能组成的正多边形只能是正方形。(具体证明可参考杨景钦在2017的国家队论文)
在这里我们只是简单理解一下该性质。如果给每种正多边形做外接圆,我们会发现,正多边形的每个点都在它的外接圆上。现在,在坐标系中任意画一个圆,我们会发现,在圆上最多只能找到四个整数坐标点,并且一定是正方形的四个点。
现在,题目就简单了许多。我们只需要枚举任意两点,判断包含这两个点的正方形的另两个点的理论位置上,是否真正存在两个点,如果两个点都存在,那么answer++。注意,如果存在一个正方形,那么这个正方形的4条边上的两个点,都满足判断条件,所以answer++重复操作4次。
判断理论点的位置是否真正存在点,为了简化操作的时间复杂度,我们可以采用两种方法:1.引入vis[ ]数组,记录每个点是否出现过;2.使用STL中的map 和 pair,详情请参考代码。
方法二的好处是空间复杂度更低,对于更大的点的数据量的情况也可以应付;并且代码更简洁;
对于方法一,从代码上来讲,似乎更好理解,但是需要我们特别注意的问题是,数组越界。题目中,坐标的范围是[-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;
}