2019-08-07 纪中NOIP模拟赛B组

T1 [JZOJ1385] 直角三角形

题目描述

  二维平面坐标系中有N个位置不同的点。

  从N个点选择3个点,问有多少选法使得这3个点形成直角三角形。

数据范围

  $3 \leq N \leq 1500$

分析

  再一次考场上正解写挂(怎么AC的一堆都是暴力卡常吸氧??)

  

  注意精度,$eps$ 尽量设小一点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 2000000001.0
#define eps 1e-15
#define N 1505

int n, ans;

struct Point {
    int x, y;
    double k;
} p[N], q[N];

bool cmp(Point a, Point b) {
    return a.k > b.k;
}

double getk(Point a, Point b) {
    if (a.x == b.x) return inf;
    if (a.y == b.y) return 0;
    return (double)(b.y - a.y) / (b.x - a.x);
}

double Abs(double a) {
    if (a < 0) return -a;
    return a;
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &p[i].x, &p[i].y);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < i; j++) q[j] = p[j];
        for (int j = i; j < n; j++) q[j] = p[j + 1];
        for (int j = 1; j < n; j++) q[j].k = getk(p[i], q[j]);
        sort(q + 1, q + n, cmp);
        queue<int> qu;
        int now = 0, last;
        while (q[++now].k > 0 && now < n) qu.push(now);
        for (; now < n; now++) {
            if (Abs(q[now].k - q[now - 1].k) < eps) {
                ans += last; continue;
            }
            last = 0;
            while (!qu.empty()) {
                int temp = qu.front();
                if (q[now].k == 0) {
                    if (q[temp].k == inf) qu.pop(), last++;
                    else break;
                }
                else {
                    double mul = q[now].k * q[temp].k;
                    if (Abs(mul + 1) < eps) qu.pop(), last++;
                    else if (mul + 1 < 0) qu.pop();
                    else break;
                }
            }
            ans += last;
        }
    }
    printf("%d", ans);
    
    return 0;
}
View Code

 T2 [JZOJ1386] 排序

猜你喜欢

转载自www.cnblogs.com/Pedesis/p/11316367.html