代码改变世界

poj 2002 Squares ----二分

2012-03-22 12:33  java环境变量  阅读(228)  评论(0编辑  收藏  举报

Squares
Time Limit: 3500MS   Memory Limit: 65536K
Total Submissions: 11185   Accepted: 4068

Description

A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating about its centre by 90 degrees gives the same polygon. It is not the only polygon with the latter property, however, as a regular octagon also has this property. 

So we all know what a square looks like, but can we find all possible squares that can be formed from a set of stars in a night sky? To make the problem easier, we will assume that the night sky is a 2-dimensional plane, and each star is specified by its x and y coordinates. 

Input

The input consists of a number of test cases. Each test case starts with the integer n (1 <= n <= 1000) indicating the number of points to follow. Each of the next n lines specify the x and y coordinates (two integers) of each point. You may assume that the points are distinct and the magnitudes of the coordinates are less than 20000. The input is terminated when n = 0.

Output

For each test case, print on a line the number of squares one can form from the given stars.

Sample Input

4
1 0
0 1
1 1
0 0
9
0 0
1 0
2 0
0 2
1 2
2 2
0 1
1 1
2 1
4
-2 5
3 7
0 0
5 2
0

Sample Output

1
6
1

                  

                题目大意:输入n个点的坐标,最多能组成多少个正方形。

         思路: 感觉这题思路不难 ,并且是放在二分专题 ,直接用二分考虑的。  我每次枚举两点作为对角线,查找 两外两个点是否存在。  最后结果除 二。    

         ps:这道题 我提交后跑了1235MS。  - - 。看到其他人交的      对于算法的优化一直不懂,时间复杂度什么的。  我试着优化代码,   还是  1219 MS,没效果。。  问题在代码中  , 请教请教。   

第一次交的代码:



//Memory: 172K		Time: 1235MS
//Language: C++		Result: Accepted
#include<stdio.h>
#include<stdlib.h>
struct point
{
	int x,y;
}p[1005];

int cmp(const void * a,const void *b)
{
	struct point * aa=(struct point *)a;
	struct point * bb=(struct point *)b;
	if(aa->x==bb->x) return aa->y - bb->y;
	return aa->x - bb->x;
}
int b_search(int a,int b,int len)       //二分找点(a,b)
{
	int max=len-1,min=0,mid;
	while(min<=max)
	{
		mid=(min+max)/2;
		if(p[mid].x==a&&p[mid].y==b) return 1;
		else if(p[mid].x>a|| ( p[mid].x==a&&p[mid].y>b) )
			max=mid-1;
		else min=mid+1;
	}
	return 0;
}
int main()
{
	//freopen("1.txt","r",stdin);
	int n,i,j,sum;
	while(scanf("%d",&n)!=EOF&&n)
	{
		sum=0;
		for(i=0;i<n;i++)
			scanf("%d%d",&p[i].x,&p[i].y);
		qsort(p,n,sizeof(p[0]),cmp);    //排序 优先按x排,再按y排
		for(i=0;i<n-1;i++)
		{
			for(j=i+1;j<n;j++)
			{
				int gx1=p[i].x+p[i].y+p[j].x-p[j].y,
					gy1=p[i].y+p[j].y+p[j].x-p[i].x,
					gx2=p[i].x+p[j].x+p[j].y-p[i].y,
					gy2=p[i].x+p[i].y+p[j].y-p[j].x;
				if(gx1%2||gx2%2||gy1%2||gy2%2) continue;    //结果只可能是整数,应为表达式中得除以二,所以分子如果是奇数全部过滤掉。
				else gx1/=2,gy1/=2,gx2/=2,gy2/=2;       //求对角线另外两点 (gx1,gy1),(gx2,gy2)
				if(b_search(gx1,gy1,n) && b_search(gx2,gy2,n)) //二分查找两点是否存在。
					sum++;
			}
		}
		printf("%d\n",sum/2);
	}
	return 0;
}

下面是修改后的代码:


//Memory: 172K		Time: 1219MS
//Language: C++		Result: Accepted
#include<stdio.h>
#include<stdlib.h>
struct point
{
	int x,y;
}p[1005];

int cmp(const void * a,const void *b)
{
	struct point * aa=(struct point *)a;
	struct point * bb=(struct point *)b;
	if(aa->x==bb->x) return aa->y - bb->y;
	return aa->x - bb->x;
}
int b_search(int a,int b,int len)
{
	int max=len-1,min=0,mid;
	while(min<=max)
	{
		mid=(min+max)/2;
		if(p[mid].x==a&&p[mid].y==b) return 1;
		else if(p[mid].x>a|| ( p[mid].x==a&&p[mid].y>b) )
			max=mid-1;
		else min=mid+1;
	}
	return 0;
}
int main()
{
	//freopen("1.txt","r",stdin);
	int n,i,j,sum;
	while(scanf("%d",&n)!=EOF&&n)
	{
		sum=0;
		for(i=0;i<n;i++)
			scanf("%d%d",&p[i].x,&p[i].y);
		qsort(p,n,sizeof(p[0]),cmp);
		for(i=0;i<n-1;i++)
		{
			for(j=i+1;j<n;j++)
			{
				int gx1=p[i].x+p[i].y+p[j].x-p[j].y;  // 修改成每一步判断。。但没效果。
				if(gx1%2) continue;
				int	gy1=p[i].y+p[j].y+p[j].x-p[i].x;
				if(gy1%2) continue;
				int gx2=p[i].x+p[j].x+p[j].y-p[i].y;
				if(gx2%2) continue;
				int gy2=p[i].x+p[i].y+p[j].y-p[j].x;
				if(gy2%2) continue;
			    gx1/=2,gy1/=2,gx2/=2,gy2/=2;
				if(!b_search(gx1,gy1,n)) continue;       //这里也是。假如 a&&b 判断的时候 如果a已经为假了 还会不会运算 b? 
				if(!b_search(gx2,gy2,n)) continue;
					sum++;
			}
		}
		printf("%d\n",sum/2);
	}
	return 0;
}