直角三角形 纪中 1385 数学_斜率

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

分析

这个解释起来比较麻烦,请自己看英文或代码。英文题解
大概就是枚举一个点和别的点连边,然后算这条线的斜率(见斜率)。
然后就把斜率排序,枚举可能垂直的两条的边(可以用一个性质,垂直的两条边的斜率乘积为-1),就可以了。

代码

const max=1500;

type
  ray=record
    dx,dy:int64;
    jpwang:longint;
end;

var
  i,j,k,n:longint;
  x:array[1..max] of longint;
  y:array[1..max] of longint;
  g:array[1..max] of ray;
  temp:array[1..max] of ray;
  num:array[0..3] of longint;
  ans:longint;

procedure turn(var r:ray);
var
  temp:int64;
begin
  temp:=r.dx;
  r.dx:=r.dy;
  r.dy:=-temp;
  r.jpwang:=(r.jpwang+1) mod 4;
end;

procedure qsort(lo,hi:longint);
var
  mid:longint;
  i,j,k:longint;
begin
  if lo<>hi
    then
      begin
        mid:=(lo+hi) div 2;
        qsort(lo,mid);
        qsort(mid+1,hi);
        i:=lo;
        j:=mid+1;
        k:=lo;
        while (i<=mid) and (j<=hi) do
          begin
            if g[i].dy*g[j].dx<g[j].dy*g[i].dx
              then
                begin
                  temp[k]:=g[i];
                  i:=i+1;
                end
              else
                begin
                  temp[k]:=g[j];
                  j:=j+1;
                end;
            k:=k+1;
          end;
        while i<=mid do
          begin
            temp[k]:=g[i];
            i:=i+1;
            k:=k+1;
          end;
        while j<=hi do
          begin
            temp[k]:=g[j];
            j:=j+1;
            k:=k+1;
          end;
        for i:=lo to hi do
          g[i]:=temp[i];
      end;
end;

begin
  readln(n);
  for i:=1 to n do
    readln(x[i],y[i]);
  ans:=0;
  for i:=1 to n do
    begin
      for j:=1 to n do
        begin
          g[j].jpwang:=0;
          g[j].dx:=x[j]-x[i];
          g[j].dy:=y[j]-y[i];
          if i=j
          then
            begin
              g[j].jpwang:=g[1].jpwang;
              g[j].dx:=g[1].dx;
              g[j].dy:=g[1].dy;
            end
          else
            while not ((g[j].dx>0) and (g[j].dy>=0)) do
              turn(g[j]);
        end;
      qsort(2,n);
      j:=2;
      while j<=n do
        begin
          fillchar(num,sizeof(num),0);
          k:=j;
          while (k<=n) and (g[j].dy*g[k].dx=g[k].dy*g[j].dx) do
            begin
              num[g[k].jpwang]:=num[g[k].jpwang]+1;
              k:=k+1;
            end;
          j:=k;
          ans:=ans+num[0]*num[1];
          ans:=ans+num[1]*num[2];
          ans:=ans+num[2]*num[3];
          ans:=ans+num[3]*num[0];
        end;
   end;
  writeln(ans);
end.

转载于:https://www.cnblogs.com/a-loud-name/p/6184767.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值