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


    平面最近点对。

    #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;
    }
    
  • 相关阅读:
    创建商品APP
    商品模块表结构分析
    sprintf 和 fprintf
    linux中sys目录
    linux中proc目录
    ioctl()函数
    ffmpeg下载安装
    【转】写给小白的实时音视频技术入门提纲
    linux常见目录解释
    linux nfs客户端开启失败解决办法
  • 原文地址:https://www.cnblogs.com/hongzy/p/11385391.html
Copyright © 2020-2023  润新知