求直角三角形的个数

题目大意:有n个点(x,y<=10^9,n<=1500),求出这n个点组成的三角形是直角三角形的方案数。

【做法1】

暴力枚举直角三角形的三个点,再用勾股定理判断是否是直角。时间复杂度O(n^3)。

【做法2】

假设原点也是点,则可以按照x轴正半轴旋转到每个点所需的角度排序,然后用单调队列扫描一遍。

如下图所示:

求直角三角形的个数_第1张图片

那么我们可以枚举每个点A作为直角三角形斜边对应的点,也就是直角点,那么其他点B的坐标就要变成——(B.x-A.x,B.y-A.y),然后按上面的方法算就可以了。

则时间复杂度O(n^2logn),编程复杂度高,容易错。

【做法3】

考虑到直角是90度,那么,将直角边上的一点旋转90度,便与另一条线重合。于是我们可以把每个点都记住它原始的象限,再每次旋转90度,旋转到第一象限内。然后按照其斜率排序,找出其斜率相同的点,则这些点都在同一直线上。统计每个象限内的点的个数,又因为1,2象限,2,3象限,3,4象限和4,1象限是相邻的。根据乘法原理和加法原理,将每个象限内的点的个数按上面的方法计算即可。具体看程序:

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define Maxn 1510
typedef long long LL;
struct Point{
	int x,y;
	int p;
	double k;
	void turn(){ x=-x; swap(x,y); }//将点“逆”时针旋转90度 
	void calc_k()//计算斜率 
	{
		if(x==0) k = 1000000001;
		else k = (0.0+y)/(0.0+x);
	}
};
bool cmp(Point x,Point y){return x.ky) return 0;
	if(y>x) return 0;
	return 1;
}
LL f[10],ans;
Point a[Maxn],b[Maxn];
int n;
int main()
{
	scanf("%d",&n);
	
	int x,y;
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
	
	for(int t=1;t<=n;t++)//枚举直角点,以这点建立平面直角坐标系 
	{
		swap(a[n],a[t]);//则a[n]为直角点 
		memset(b,0,sizeof(b));
		for(int i=1;i=0 && y<0)
			{
				b[i].turn(); b[i].turn(); b[i].turn();
				b[i].p = 4;
			}
			else if(x<0 && y<=0)
			{
				b[i].turn(); b[i].turn();
				b[i].p = 3;
			}
			else if(x<=0 && y>0)
			{
				b[i].turn();
				b[i].p = 2;
			}
			else b[i].p = 1;
			b[i].calc_k();
		}
		sort(b+1,b+n,cmp);//排序 
		int i,j;
		for(i=1;i
这个做法简单,不易错。时间复杂度也是O(n^2logn)。

转载于:https://www.cnblogs.com/ouqingliang/p/9245257.html

你可能感兴趣的:(求直角三角形的个数)