您的位置:首页 > 大数据 > 人工智能

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: