pku 2002Squares 二分查找

题意:给你n个点的坐标,算出这些坐标可能组成多少个正方形。。

分析:由几何知识我们可以推出,当知道一个正方形一条边两个点的坐标时,可以推出剩下两点的坐标。

推导过程:

  1. 公式推导 :  
  2. 如图所示,正方形的四个点分别为 (x1,y1),(x2,y2),(x3,y3),(x4,y4)  
  3. 假设一开始给出的点为  (x1,y1),(x2,y2) 且已排序  
  4. 根据全等三角形,可以得知2个蓝色△全等,2个红色△全等 (注:此处也可推右边的正方形)  
  5. 所以可以推出 x3=x2-(y2-y1);  
  6.                  y3=y2+(x2-x1);  
  7.                  x4=x1-(y2-y1);  
  8.                  y4=y1+(x2-y1);  
  9. 当然全体是排好序。 因为这样子做会导致边被重用,所以需除于 2 ,具体追究可自己详细思考

知道了另外两点的坐标,就可以在所有点的坐标中用二分查找来查找是否存在。。

#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x, y;
}p[1007];
int n;
int cmp(node a, node b)
{
    if(a.x==b.x)    return a.y < b.y;
    return a.x <b.x;
}
bool bsearch(int x, int y, int low, int high)
{
    while(low <= high)
    {
        int m=(low + high)/2;
        if(p[m].x == x && p[m].y == y)    return true;
        else if(p[m].x < x)    low=m+1;
        else if(p[m].x >x)    high=m-1;
        else{
            if (p[m].y > y)
            high = m -1;
            else
            low = m + 1;
        }
    }
    return false;
}
int main()
{
    int i, j, sum;
    while(cin>>n && n)
    {
        sum=0;
        for(i=0; i<n; ++i)
        {
            cin>>p[i].x>>p[i].y;
        }
        sort(p, p+n, cmp);
        for (i = 0; i < n; ++i)
        {
            for (j = i + 1; j < n; ++j)
            {
                int x3=p[j].x-(p[j].y-p[i].y);
                int y3=p[j].y+(p[j].x-p[i].x);
                if(!bsearch(x3,y3,0,n))
                    continue;
                int x4=p[i].x-(p[j].y-p[i].y);
                int y4=p[i].y+(p[j].x-p[i].x);
                if(!bsearch(x4,y4,0,n))
                    continue;
                sum++;
            }
        }
        printf("%d\n",sum/2);
    }
    return 0;
}

这道题还可以用hash表来解决。。

posted @ 2014-03-03 16:47  xtaq  阅读(217)  评论(0编辑  收藏  举报