POJ 2002--Squares

30 篇文章 0 订阅
5 篇文章 0 订阅
  • 题目要求四点能组成正方形的个数,若直接枚举四点,会TLE。可以根据正方形公式,题目有提示,正方形旋转90度与原图形重合。
  1. 我们可以枚举对角线,只有5*10^5个,根据对角线经过中点旋转,来得到另外的两点。可以形象地理解已知A(x1,y1),C(x2,y2)为正方形对角线,经过旋转AB边在x,y轴上的投影长度会互换调。
  2.  即是假设另两点为B(x3,y3),D(x4,y4),正方形ABCD,有:
  • x3+x4 = x1+x2;
  • y3+y4 = y1+y2;(对角线中点重叠)
  • x4-x3 = y1-y2;y4-y3 = x2-x1;(旋转之后边的投影长度互换),解以上方程可得BD。
  1. 优化:因为B,D坐标必须为整数,所以以上枚举边时所得式必须得出整除结果,因为我们是从点枚举边,所以j = i+1,即每条边只枚举一次。又因为对角线有两条,在枚举到另一条对角线,最好是不用再判断了,最开始使用了map将点和第几点的i,j对应起来,map比较慢。然后考虑到就算枚举了另一条对角线,也只增加一个正方形,所以最后结果除以2.
  2. Hash函数一直用的不好,Hash保存已给点的坐标,key值为坐标经过变换而得,因为坐标x或y属于(-20000,20000),所以坐标对总共有1.6*10^9个,需要散列处理,经过试验,选择500000左右的素数是比较理想的。 px前面的加权有坐标上限确定。
hash:
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxN 499927
#define maxM 1001
#define maxL 11

struct node
{
    int px,py;
    node* next;
}* hashTab[maxN];
struct _node
{
    int px,py;
}point[maxM];

bool check(int x,int y)
{
    int slot = (x*maxL+y)%maxN;
    node* nowNode;
    for(nowNode = hashTab[slot];nowNode != NULL;nowNode = nowNode->next)
    {
        if(nowNode->px == x&&nowNode->py == y)
            return true;
    }
    return false;
}

int main()
{
    int N;
    int i,j;
    int slot;
    int squareNum;
    int x1,x2,x3,x4,y1,y2,y3,y4;
    node* tmpNode;
    int nodeNum1,nodeNum2;
    while(scanf("%d",&N))
    {
        if(!N)
            return 0;
        squareNum = 0;
        memset(hashTab,0,sizeof(hashTab));
        for(i = 0;i < N;i++)
        {
            scanf("%d%d",&point[i].px,&point[i].py);
            point[i].px += 20000;
            point[i].py += 20000;
            tmpNode = new node;
            tmpNode->px = point[i].px;
            tmpNode->py = point[i].py;
            slot = (point[i].px*maxL+point[i].py)%maxN;
            tmpNode->next = hashTab[slot];
            hashTab[slot] = tmpNode;
        }
        for(i = 0;i < N;i++)
        {
        x1 = point[i].px;
        y1 = point[i].py;
        for(j = i+1;j < N;j++)
        {
            x2 = point[j].px;
            y2 = point[j].py;
            if((x1+x2+y2-y1)%2 == 0)
            x3 = (x1+x2+y2-y1)/2;
            else
            continue;
            if((x1+x2+y1-y2)%2 == 0)
            x4 = (x1+x2+y1-y2)/2;
            else
            continue;
            if((y1+y2+x1-x2)%2 == 0)
            y3 = (y1+y2+x1-x2)/2;
            else
            continue;
            if((y1+y2+x2-x1)%2 == 0)
            y4 = (y1+y2+x2-x1)/2;
            else
            continue;
            if(check(x3,y3)&&check(x4,y4))
            {
                squareNum++;
            }
        }
        }
        printf("%d\n",squareNum/2);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值