zoukankan      html  css  js  c++  java
  • poj2002 poj3432 正方形个数 (hash,二分)

    给出一堆点,求其中正方形的个数。

    题目很简单,如果枚举,复杂度为O(n^4),肯定超时,我们利用hash,或者二分来降低复杂度,枚举其中的两个点,然后利用正方形的性质求出其余的两个点,然后判断这两个点是否都存在,如果存在,说明可以组成一个正方形。判断的方式利用hash或者二分都可以,这个题目用的hash,poj3432用的二分。下面的问题就是给出两个点,如何求出其余的两个顶点。

    给出两个点(a1,a2),(b1,b2),我们得到其余两个顶点为(a1+(b2-a2),a2-(b1-a1)),(b1+(b2-a2),b2-(b1-a1)),或者
    (a1-(b2-a2), a2+(b1-a1)),( b1-(b2-a2), b2+(b1-a1)),我们只考虑一种情况就可以了,否则也是重复计算。这样对于同一个
    正方形,每条边都计算了一遍(顶点已经排序),只是我们只计算每条边对应的左上方或者右下方的矩形,这样只有两条边对应的计算了一次,因此
    需要将计数/2。

    poj2002

    代码:

    View Code
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <stdio.h>
    using namespace std;
    const int N=1010;
    const int M=40010;
    struct m_point{
    int x,y;
    };
    m_point s[N];
    int m_hash[M],next[N],n;
    bool cmp(const m_point &p1,const m_point &p2)
    {
    if(p1.x < p2.x)
    return true;
    if((p1.x == p2.x) && (p1.y < p2.y))
    return true;
    return false;
    }
    bool isExist(int x,int y)
    {
    int value=abs(x+y);
    int index=m_hash[value];
    while(-1 != index)
    {
    if((s[index].x == x) && (s[index].y == y))
    return true;
    index=next[index];
    }
    return false;
    }
    int main()
    {
    int i,j,value,new_x,new_y,ans=0;
    m_point tmp;
    while(scanf("%d",&n) && n)
    {
    ans=0;
    memset(next,-1,sizeof(next));
    memset(m_hash,-1,sizeof(m_hash));
    for(i=0;i<n;++i)
    scanf("%d%d",&s[i].x,&s[i].y);
    sort(s,s+n,cmp);
    for(i=0;i<n;++i)
    {
     //hash函数是采用的两个坐标的和,和相同的用类似与链表连接起来
    value=abs(s[i].x+s[i].y);
    next[i]=m_hash[value];//技巧和图的邻接表存储方式相同
    m_hash[value]=i;
    }
    // for(i=0;i<n;++i)
    // cout<<s[i].x<<" "<<s[i].y<<'\t';
    // cout<<endl;
    for(i=0;i<n;++i)
    {
    for(j=i+1;j<n;++j)
    {
    tmp.x=s[j].x-s[i].x;
    tmp.y=s[j].y-s[i].y;
    new_x=s[i].x+tmp.y;
    new_y=s[i].y-tmp.x;
    if(!isExist(new_x,new_y))
    continue;
    new_x=s[j].x+tmp.y;
    new_y=s[j].y-tmp.x;
    if(!isExist(new_x,new_y))
    continue;
    ++ans;
    }
    }
    printf("%d\n",ans/2);
    }
    return 0;
    }

    poj3432

    代码:

    View Code
    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    using namespace std;
    const int N=2002;
    struct m_point{
    int x,y;
    };
    int n;
    m_point p[N];
    bool cmp(const m_point &p1,const m_point &p2)
    {
    if(p1.x < p2.x)
    return true;
    if((p1.x == p2.x) && (p1.y < p2.y))
    return true;
    return false;
    }
    bool find_point(m_point &t)
    {
    int left=0,right=n,mid;
    while(left<=right)
    {
    mid=(left+right)>>1;
    if((p[mid].x == t.x) && (p[mid].y == t.y))
    return true;
    if(cmp(t,p[mid]))
    right=mid-1;
    else
    left=mid+1;
    }
    return false;
    }

    int main()
    {
    int i,j,ans;
    m_point tmp,new_node;
    while(scanf("%d",&n) != EOF)
    {
    for(i=0;i<n;++i)
    scanf("%d%d",&p[i].x,&p[i].y);
    sort(p,p+n,cmp);
    ans=0;
    for(i=0;i<n;++i)
    {
    for(j=i+1;j<n;++j)
    {
    tmp.x=p[j].x-p[i].x;
    tmp.y=p[j].y-p[i].y;
    new_node.x=p[i].x+tmp.y;
    new_node.y=p[i].y-tmp.x;
    if(!find_point(new_node))
    continue;
    new_node.x=p[j].x+tmp.y;
    new_node.y=p[j].y-tmp.x;
    if(!find_point(new_node))
    continue;
    ++ans;
    }
    }
    printf("%d\n",ans/2);
    }
    return 0;
    }



  • 相关阅读:
    动态采样
    Java Mail无法解析带分号的收件人列表的问题
    git 使用详解(5) get log 查看提交历史
    git 使用详解(6) 撤消操作
    修改 android的 开机 音乐
    修改 android的 开机 音乐
    关于ubuntu的aptget 包
    ubuntu 10.04 常用 设置
    Android4.0.3 修改 启动 动画
    git 使用详解(5) get log 查看提交历史
  • 原文地址:https://www.cnblogs.com/buptLizer/p/2274811.html
Copyright © 2011-2022 走看看