hdu 多校联赛 Regular polygon

来源:互联网 发布:中国联通软件研究院吧 编辑:程序博客网 时间:2024/06/05 09:36

Regular polygon

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2924    Accepted Submission(s): 685


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
40 00 11 01 160 00 11 01 12 02 1
 

Sample Output
12

这道题做的时候没啥好的思路 后来去百度竟然百度到了相似的题目 改了几遍代码后就ac了(虽然ac之前多次莫名奇妙的re)百度上的解法是解释了一波坐标系上的点形成的正多边形只能是正方形 先在这些点中循环任意的俩个点 一个正方形确定了两点之后就能知道另外两个点的坐标 再看这两个点之外的点有没有符合条件的  代码中有两个设计巧妙的地方 一个是用矩阵的位置来表示坐标 标记矩阵(这个坐标有这个点就标记1 其他为零) 后直接判断这个坐标的矩阵内有没有这个点 这样可以降低时间复杂度 把纯暴力对比坐标的o(n^2)变成了o(1) 另一个则是负坐标的处理 因为如果你用矩阵的位置来标记点 就不能标记负坐标的点 所以数据输入时就把所有的数据都+200(坐标的范围是-100到100,所以只要加的是大于100就行)所有点的横纵坐标都加上一个相同的数 点之间的位置关系不会改边 却很好的排除了难以处理的负数。

ac代码:

#include<bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define inf 0x3f3f3f3f#define N 250010#define ll long longusing namespace std;int vis[500][500];//用来标记点的矩阵struct Point//定义一个结构体用来存储点的坐标{    int x,y;} p[555];int solve(Point a,Point b)//一个正方形坐标系中知道了一条边上的两点就可以算出另外的两点 如果存在这另外的两点 正方形总个数加一{    int x=a.x-b.x;    int y=a.y-b.y;    int ans=0;    if(a.x+y>=0&&a.y-x>=0&&b.x+y>=0&&b.y-x>=0&&vis[a.x+y][a.y-x]&&vis[b.x+y][b.y-x])//对比是否存在着另外的两点        ans++;    if(a.x-y>=0&&a.y+x>=0&&b.x-y>=0&&b.y+x>=0&&vis[a.x-y][a.y+x]&&vis[b.x-y][b.y+x])        ans++;    return ans;}int main(){    int n,a,b;    while(~scanf("%d",&n))    {        mem(vis,0);//每一次输入清空原标记数组        for(int i=0; i<n; i++)        {            scanf("%d%d",&a,&b);//输入数据            a+=200;//这一步是非常巧妙的一步 将所有的原坐标+200再存入处理数组            b+=200;//因为数组坐标不能为负 这样可以防止数组越界            p[i].x=a;            p[i].y=b;            vis[a][b]=1;//标记点        }        int ans=0;        for(int i=0; i<n; i++)//暴力遍历所有的两点            for(int j=i+1; j<n; j++)                if(i!=j)//跳过点和点本身                    ans+=solve(p[i],p[j]);//用函数判断是是否存在另外两点形成正方形        printf("%d\n",ans/4);//因为上面的循环是遍历了所有的两点 那么以两点形成的正方形 一个正方形可以被四对两点表示 一个正方形就被记了四次 所以最后要去重除以四    }}