「学习笔记」杂项算法学习笔记

平面最近点对。

#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;
}
原文地址:https://www.cnblogs.com/hongzy/p/11385391.html