平面最近点对。
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
#define fs first
#define sc second
typedef double db;
typedef pair<db, db> pa;
const int N = 2e5 + 10;
const db EPS = 1e-10;
int cmp1(pa a, pa b) { return a.fs - b.fs < -EPS; }
int cmp2(pa a, pa b) { return a.sc - b.sc < -EPS; }
int n, m;
pa a[N], arr[N];
db p(db x) { return x * x; }
db d(pa x, pa y) { return sqrt(p(x.fs - y.fs) + p(x.sc - y.sc)); }
db divide(int l, int r) {
if(r - l <= 2) {
db ans = 3e18;
for(int i = l; i < r; i ++)
for(int j = i + 1; j <= r; j ++)
ans = min(ans, d(a[i], a[j]));
sort(a + l, a + r + 1, cmp2);
return ans;
}
int mid = (l + r) >> 1, p1 = l, p2 = mid + 1;
db Mid = a[mid].fs, ans = min(divide(l, mid), divide(mid + 1, r));
for(int i = l; i <= r; i ++) {
if(p2 > r || (p1 <= mid && a[p1].sc - a[p2].sc < -EPS)) arr[i] = a[p1 ++];
else arr[i] = a[p2 ++];
}
m = 0;
for(int i = l; i <= r; i ++) a[i] = arr[i];
for(int i = l; i <= r; i ++) if(fabs(a[i].fs - Mid) <= ans) arr[++ m] = a[i];
for(int i = 1; i <= m; i ++)
for(int j = i + 1; j <= i + 7 && j <= m; j ++) {
db dis = d(arr[i], arr[j]);
ans = min(ans, dis);
}
return ans;
}
int main() {
while(~ scanf("%d", &n)) {
for(int i = 1; i <= n; i ++)
scanf("%lf%lf", &a[i].fs, &a[i].sc);
sort(a + 1, a + n + 1, cmp1);
printf("%.4lf
", divide(1, n));
}
return 0;
}
康托展开
int rk(int *p) {
int y = 0;
for(int i = 1; i <= 9; i ++) {
int x = p[i] - 1;
for(int j = 1; j < i; j ++)
if(p[j] < p[i]) x --;
y += x * fac[9 - i];
}
return y + 1;
}
void pmt(int rk, int *p) {
rk --;
static bool vis[N];
fill(vis + 1, vis + 10, 0);
for(int i = 1; i <= 9; i ++) {
int c = rk / fac[9 - i];
rk -= c * fac[9 - i];
for(int j = 1; j <= 9; j ++) if(!vis[j]) {
if(!c --) { p[i] = j; break ; }
}
vis[p[i]] = 1;
}
}
计算几何 - 半平面交
typedef double db;
const db eps = 1e-9;
const int N = 210;
int sign(db x) { return fabs(x) < eps ? 0 : (x > eps ? 1 : -1); }
struct point {
db x, y;
void _int() { int a, b; scanf("%d%d", &a, &b); x = a; y = b; }
point operator + (point b) { return (point) {x + b.x, y + b.y}; }
point operator - (point b) { return (point) {x - b.x, y - b.y}; }
point operator * (db b) { return (point) {x * b, y * b}; }
void operator += (point b) { x += b.x; y += b.y; }
void operator -= (point b) { x -= b.x; y -= b.y; }
void operator *= (db b) { x *= b; y *= b; }
db dot(point b) { return x * b.x + y * b.y; }
db det(point b) { return x * b.y - y * b.x; }
db length() { return sqrt(x * x + y * y); }
db disto(point b) { return ((*this) - b).length(); }
point left_mover(db len) {
point tr = *this;
swap(tr.x, tr.y); tr.x *= -1;
tr *= len / tr.length();
return tr;
}
db alpha() { return atan2(y, x); }
} a[N];
struct seg {
point a, b;
db alpha() { return (b - a).alpha(); }
void left_move(db len) {
point trans = (b - a).left_mover(len);
a += trans; b += trans;
}
friend point V(seg x) { return x.b - x.a; }
} e[N];
int n, r;
bool cmp(seg a, seg b) {
db k1 = a.alpha(), k2 = b.alpha();
if(fabs(k1 - k2) > eps) return k1 < k2;
return sign(V(b).det(a.a - b.a)) == 1;
}
point its(seg l1, seg l2) {
point &a = l1.a, &b = l1.b, &c = l2.a, &d = l2.b;
b -= a; d -= c;
db k1 = (c.det(d) - a.det(d)) / b.det(d);
return a + b * k1;
}
void solve() {
static seg q[N];
static point t[N];
int l = 0, r = 0;
sort(e + 1, e + n + 1, cmp);
for(int i = 1; i <= n; i ++) if(i == 1 || sign(e[i].alpha() - e[i - 1].alpha())) {
while(r - l > 1 && sign((t[r - 1] - e[i].a).det(V(e[i]))) == 1) r --;
while(r - l > 1 && sign((t[l + 1] - e[i].a).det(V(e[i]))) == 1) l ++;
q[r ++] = e[i];
if(r - l > 1) t[r - 1] = its(q[r - 2], q[r - 1]);
}
while(r - l > 1 && sign((t[r - 1] - q[l].a).det(V(q[l]))) == 1) r --;
if(r - l > 2) {
t[l] = its(q[l], q[r - 1]);
db dis = -1, x1, y1, x2, y2;
for(int i = l; i < r; i ++) {
for(int j = i + 1; j < r; j ++) {
db d = t[i].disto(t[j]);
if(d > dis) {
dis = d; x1 = t[i].x; y1 = t[i].y;
x2 = t[j].x; y2 = t[j].y;
}
}
}
printf("%.4f %.4f %.4f %.4f
", x1, y1, x2, y2);
}
}
一般式&直线(两点表示)的交点
typedef double db;
db A, B, C;
struct point { db x, y; };
db f(point a) { return A * a.x + B * a.y + C; }
point its(point a, point b) {
db u = fabs(f(a)), v = fabs(f(b));
return (point) {
(a.x * v + b.x * u) / (u + v),
(a.y * v + b.y * u) / (u + v)
};
}
两圆求交(靠上面的交点)
struct point { db x, y; } a[N];
point operator + (point a, point b) { return {a.x + b.x, a.y + b.y}; }
point operator - (point a, point b) { return {a.x - b.x, a.y - b.y}; }
point operator * (db k, point a) { return {a.x * k, a.y * k}; }
db dot(point a, point b) { return a.x * b.x + a.y * b.y; }
db det(point a, point b) { return a.x * b.y - a.y * b.x; }
db dis(point a, point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
db len(point a) { return sqrt(a.x * a.x + a.y * a.y); }
point rot90(point a) { return {- a.y, a.x}; }
point lento(point a, db h) { return (h / len(a)) * a; }
void roundp(point &a) { a.x = round(a.x); a.y = round(a.y); }
struct Edge { int v; db d; };
struct Node { int u, v, la; };
int n, m, d[N];
bitset<N> tag[N], vis, bG[N];
vector<Edge> G[N];
queue<Node> q;
point get(int u, int v, db du, db dv) {
db d = dis(a[u], a[v]);
db L = (du * du + d * d - dv * dv) / (2 * d);
db H = sqrt(du * du - L * L);
point vec = a[v] - a[u]; vec = rot90(vec); vec = lento(vec, H);
return a[u] + lento(a[v] - a[u], L) + vec;
}