JZOJ 1385. 直角三角形

泄露秘密 提交于 2019-11-26 10:34:32

题目

Description

  二维平面坐标系中有N个点。
  从N个点选择3个点,问有多少选法使得这3个点形成直角三角形。
 

Input

  第一行包含一个整数N(3<=N<=1500),表示点数。
  接下来N行,每行包含两个用空格隔开的整数表示每个点的坐标,坐标值在-10^9到10^9之间。
  每个点位置互不相同。

Output

  输出直角三角形的数量。
 

Sample Input

输入1:
3
4 2
2 1
1 3

输入2:
4
5 0
2 6
8 6
5 7

输入3:
5
-1 1
-1 0
0 0
1 0
1 1

Sample Output

输出1:
1

输出2:
0

输出3:
7
 

Data Constraint

 

分析

 

  • 首先,我们肯定要两两枚举
  • 然后,我们需要知道斜率
  • 在坐标系中 一次函数 y=kx k就是斜率
  • 二次函数 y=kx+b k也是斜率
  • 因为直角三角形两边斜率相乘是-1
  • 根据这个性质我们可以知道构成三角形是斜率相等但在不同象限的点
  • 所以我们就求斜率相同的点
  • 然后我们就可以有一个排序来优化
  • 相同的斜率的一定在一起
  • 答案就是讲相邻两象限的相同斜率的点乘起来再相加

 

代码

 

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 long long x[10010],y[10001];
 5 struct sb
 6 {
 7     long long x,y,xx;
 8 }tmp[10001];
 9 void turn(int p)
10 {
11     swap(tmp[p].x,tmp[p].y);
12     tmp[p].y=-tmp[p].y;
13     tmp[p].xx=(tmp[p].xx+1)%4;
14 }
15 bool cmp(sb a,sb b)
16 {
17     return a.x*b.y>b.x*a.y;
18 }
19 int cnt;
20 int main ()
21 {
22     int n;
23     cin>>n;
24     for (int i=1;i<=n;i++) cin>>x[i]>>y[i];
25     for (int i=1;i<=n;i++)
26     {
27         for (int j=1;j<=n;j++)
28         {
29             tmp[j].x=x[j]-x[i];
30             tmp[j].y=y[j]-y[i];
31             tmp[j].xx=0;
32             if (i==j)
33             {
34                 tmp[j].x=tmp[1].x;
35                 tmp[j].y=tmp[1].y;
36                 tmp[j].xx=tmp[1].xx;
37             }
38             else 
39               while (tmp[j].x<=0||tmp[j].y<0) turn(j);
40         }
41         sort(tmp+2,tmp+n+1,cmp);
42         int j=2;
43         while (j<=n)
44         {
45             int ans[4]={0};
46             int k=j;
47             while (k<=n&&tmp[j].x*tmp[k].y==tmp[k].x*tmp[j].y)
48                 ans[tmp[k].xx]++,k++;
49             for (int kk=0;kk<=3;kk++)
50               cnt+=ans[kk]*ans[(kk+1)%4];
51             j=k; 
52         }
53     }
54     cout<<cnt;
55 } 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!