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; }
T2 [JZOJ1386] 排序