pku 2002Squares 二分查找
题意:给你n个点的坐标,算出这些坐标可能组成多少个正方形。。
分析:由几何知识我们可以推出,当知道一个正方形一条边两个点的坐标时,可以推出剩下两点的坐标。
推导过程:
- 公式推导 :
- 如图所示,正方形的四个点分别为 (x1,y1),(x2,y2),(x3,y3),(x4,y4)
- 假设一开始给出的点为 (x1,y1),(x2,y2) 且已排序
- 根据全等三角形,可以得知2个蓝色△全等,2个红色△全等 (注:此处也可推右边的正方形)
- 所以可以推出 x3=x2-(y2-y1);
- y3=y2+(x2-x1);
- x4=x1-(y2-y1);
- y4=y1+(x2-y1);
- 当然全体是排好序。 因为这样子做会导致边被重用,所以需除于 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表来解决。。