Description
在一个平面直角坐标系中,给你 $ n(2≤n≤50) $ 个点的坐标。这 $ n $ 个点中,每两个点之间都有一条直线(注意不是线段) 相连。求:这些直线中,有多少对直线相交。
1.当多点共线时,不认为由这几个点产生的直线有交点;
2.多条直线交于一点时,并不代表这几条直线在这个点相交时只产生一个交点,而是每两条直线都要统计一次。
Solution
熟悉一下板子(这题为什么有1900?)
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
#define pb push_back
typedef double db;
const db eps = 1e-6;
const db pi = acos(-1);
int sign(db k) {
if (k > eps) return 1; else if (k < -eps) return -1; return 0;
}
int cmp(db p1, db p2) { return sign(p1 - p2); }
int inmid(db p1, db p2, db p3) { return sign(p1 - p3) * sign(p2 - p3) <= 0; }
struct point {
db x, y;
point operator + (const point& p1) const { return (point) { p1.x + x, p1.y + y }; }
point operator - (const point& p1) const { return (point) { x - p1.x, y - p1.y }; }
point operator * (db p1) const { return (point) { x* p1, y* p1 }; }
point operator / (db p1) const { return (point) { x / p1, y / p1 }; }
int operator == (const point& p1) const { return cmp(x, p1.x) == 0 && cmp(y, p1.y) == 0; }
// 逆时针旋转
point turn(db p1) { return (point) { x* cos(p1) - y * sin(p1), x* sin(p1) + y * cos(p1) }; }
point turn90() { return (point) { -y, x }; }
bool operator < (const point p1) const {
int a = cmp(x, p1.x);
if (a == -1) return 1; else if (a == 1) return 0; else return cmp(y, p1.y) == -1;
}
db abs() { return sqrt(x * x + y * y); }
db abs2() { return x * x + y * y; }
db dis(point p1) { return ((*this) - p1).abs(); }
point unit() { db w = abs(); return (point) { x / w, y / w }; }
void scan() { double p1, p2; scanf("%lf%lf", &p1, &p2); x = p1; y = p2; }
void print() { printf("%.11lf %.11lf ", x, y); }
db getw() { return atan2(y, x); }
point getdel() { if (sign(x) == -1 || (sign(x) == 0 && sign(y) == -1)) return (*this) * (-1); else return (*this); }
int getP() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) == -1); }
};
int inmid(point p1, point p2, point p3) { return inmid(p1.x, p2.x, p3.x) && inmid(p1.y, p2.y, p3.y); }
db cross(point p1, point p2) { return p1.x * p2.y - p1.y * p2.x; }
db dot(point p1, point p2) { return p1.x * p2.x + p1.y * p2.y; }
db rad(point p1, point p2) { return atan2(cross(p1, p2), dot(p1, p2)); }
// -pi -> pi
int compareangle(point p1, point p2) {
return p1.getP() < p2.getP() || (p1.getP() == p2.getP() && sign(cross(p1, p2)) > 0);
}
point proj(point p1, point p2, point q) { // q 到直线 p1,p2 的投影
point k = p2 - p1; return p1 + k * (dot(q - p1, k) / k.abs2());
}
point reflect(point p1, point p2, point q) { return proj(p1, p2, q) * 2 - q; }
int clockwise(point p1, point p2, point p3) {// p1 p2 p3 逆时针 1 顺时针 -1 否则 0
return sign(cross(p2 - p1, p3 - p1));
}
int checkLL(point p1, point p2, point p3, point p4) {// 求直线 (L) 线段 (S)p1,p2 和 p3,p4 的交点
return cmp(cross(p3 - p1, p4 - p1), cross(p3 - p2, p4 - p2)) != 0;
}
point getLL(point p1, point p2, point p3, point p4) {
db w1 = cross(p1 - p3, p4 - p3), w2 = cross(p4 - p3, p2 - p3); return (p1 * w2 + p2 * w1) / (w1 + w2);
}
int intersect(db l1, db r1, db l2, db r2) {
if (l1 > r1) swap(l1, r1); if (l2 > r2) swap(l2, r2); return cmp(r1, l2) != -1 && cmp(r2, l1) != -1;
}
int checkSS(point p1, point p2, point p3, point p4) {
return intersect(p1.x, p2.x, p3.x, p4.x) && intersect(p1.y, p2.y, p3.y, p4.y) &&
sign(cross(p3 - p1, p4 - p1)) * sign(cross(p3 - p2, p4 - p2)) <= 0 &&
sign(cross(p1 - p3, p2 - p3)) * sign(cross(p1 - p4, p2 - p4)) <= 0;
}
db disSP(point p1, point p2, point q) {
point p3 = proj(p1, p2, q);
if (inmid(p1, p2, p3)) return q.dis(p3); else return min(q.dis(p1), q.dis(p2));
}
db disSS(point p1, point p2, point p3, point p4) {
if (checkSS(p1, p2, p3, p4)) return 0;
else return min(min(disSP(p1, p2, p3), disSP(p1, p2, p4)), min(disSP(p3, p4, p1), disSP(p3, p4, p2)));
}
int onS(point p1, point p2, point q) { return inmid(p1, p2, q) && sign(cross(p1 - q, p2 - p1)) == 0; }
struct line {
// p[0]->p[1]
point p[2];
line(){}
line(point p1, point p2) { p[0] = p1; p[1] = p2; }
point& operator [] (int k) { return p[k]; }
int include(point k) { return sign(cross(p[1] - p[0], k - p[0])) > 0; }
int ons(point k) {
point a=k-p[0],b=p[1]-p[0];
return cmp(a.x*b.y,b.x*a.y)==0;
}
point dir() { return p[1] - p[0]; }
line push() { // 向外 ( 左手边 ) 平移 eps
const db eps = 1e-6;
point delta = (p[1] - p[0]).turn90().unit() * eps;
return { p[0] - delta,p[1] - delta };
}
};
int checkLL(line p1, line p2) { return checkLL(p1[0], p1[1], p2[0], p2[1]); }
point getLL(line p1, line p2) { return getLL(p1[0], p1[1], p2[0], p2[1]); }
int parallel(line p1, line p2) { return sign(cross(p1.dir(), p2.dir())) == 0; }
int sameDir(line p1, line p2) { return parallel(p1, p2) && sign(dot(p1.dir(), p2.dir())) == 1; }
int operator < (line p1, line p2) {
if (sameDir(p1, p2)) return p2.include(p1[0]);
return compareangle(p1.dir(), p2.dir());
}
int checkpos(line p1, line p2, line p3) { return p3.include(getLL(p1, p2)); }
int n,cnt;
long long ans;
point p[105];
line l[10005];
signed main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) p[i].scan();
for(int i=1;i<=n;i++) {
for(int j=1;j<i;j++) {
line tmp(p[i],p[j]);
int flag=1;
for(int k=1;k<=cnt;k++) {
if(parallel(l[k],tmp)) {
if(tmp.ons(l[k].p[0]) || tmp.ons(l[k].p[1]) ||
l[k].ons(tmp.p[0]) || l[k].ons(tmp.p[1])) {
flag=0;
}
}
}
if(flag) l[++cnt]=tmp;
}
}
for(int i=1;i<=cnt;i++) {
for(int j=1;j<i;j++) {
if(checkLL(l[i],l[j])) ++ans;
}
}
cout<<ans;
}