zoukankan      html  css  js  c++  java
  • LOJ #2008. 「SCOI2015」小凸想跑步(半平面交)

    https://loj.ac/problem/2008

    题解:

    当板题复习写了。

    • 枚举要的那个三角形和其它三角形,用叉积列出不等式,不难发现是(ax+by+c>=0)的形式,这就是一个半平面。

    • 随便取(ax+by+c=0)直线上一点,加上向量((b,-a)) 就是半平面的对应向量了。

    • 然后加上原来凸包上的边做个半平面交就好了。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    #define db double
    
    const db pi = acos(-1);
    
    struct P {
    	db x, y;
    	P(db _x = 0, db _y = 0) {
    		x = _x, y = _y;
    	}
    };
    
    P operator + (P a, P b) { return P(a.x + b.x, a.y + b.y);}
    P operator - (P a, P b) { return P(a.x - b.x, a.y - b.y);}
    db dot(P a, P b) { return a.x * b.x + a.y * b.y;}
    db operator ^ (P a, P b) { return a.x * b.y - a.y * b.x;}
    P operator * (P a, db b) { return P(a.x * b, a.y * b);}
    
    struct L {
    	P p, v;
    	L() {}
    	L(P _p, P _v) { p = _p, v = _v;}
    };
    
    P jd(L a, L b) { return b.p + b.v * ((a.v ^ (a.p - b.p)) / (a.v ^ b.v));}
    int onr(P a, L b) { return ((a - b.p) ^ b.v) > 0;}
    
    const int N = 2e5 + 5;
    
    int n;
    P a[N];
    
    L b[N]; int b0;
    
    const db eps = 1e-8;
    
    struct nod {
    	L x; db v;
    } d[N]; int d0;
    
    db jj(P a) { return atan2(a.y, a.x);}
    
    int cmpd(nod a, nod b) {
    	if(abs(a.v - b.v) > eps) return a.v < b.v;
    	return onr(b.x.p, a.x);
    }
    
    L z[N]; int st, en;
    
    db ans;
    
    db qry(P *a, int n) {
    	db s = 0;
    	fo(i, 2, n - 1) s += (a[i] - a[1]) ^ (a[i + 1] - a[1]);
    	return s / 2;
    }
    
    db solve() {
    	fo(i, 1, b0) d[++ d0] = (nod) {b[i], jj(b[i].v)};
    	sort(d + 1, d + d0 + 1, cmpd);
    	int D = d0; d0 = 0;
    	fo(i, 1, D) if(!d0 || abs(d[d0].v - d[i].v) > eps)
    		d[++ d0] = d[i];
    	st = 1; en = 0;
    	fo(i, 1, d0) {
    		L x = d[i].x;
    		while(st < en && onr(jd(z[st], z[st + 1]), x)) st ++;
    		while(st < en && onr(jd(z[en], z[en - 1]), x)) en --;
    		z[++ en] = x;
    	}
    	while(st < en - 1 && onr(jd(z[en], z[en - 1]), z[st])) en --;
    	while(st < en - 1 && onr(jd(z[st], z[st + 1]), z[en])) st ++;
    	if(en - st + 1 < 3) return 0;
    	static P c[N]; int c0 = 0;
    	fo(i, st, en) c[++ c0] = jd(z[i], i == en ? z[st] : z[i + 1]);
    	return qry(c, c0);
    }
    
    int main() {
    	scanf("%d", &n);
    	fo(i, 1, n) scanf("%lf %lf", &a[i].x, &a[i].y);
    	fo(i, 1, n)	b[++ b0] = L(a[i], a[i % n + 1] - a[i]);
    	fo(i, 2, n) {
    		db u = 0, v = 0, w = 0;
    		db x0 = a[1].x, y0 = a[1].y, x1 = a[2].x, y1 = a[2].y;
    		u += y0 - y1; v += x1 - x0; w += x0 * y1 - x1 * y0;
    		
    		x0 = a[i].x, y0 = a[i].y, x1 = a[i % n + 1].x, y1 = a[i % n + 1].y;
    		u -= y0 - y1; v -= x1 - x0; w -= x0 * y1 - x1 * y0;
    		
    		u = -u, v = -v, w = -w;
    		
    		P p;
    		if(abs(v) < eps) {
    			if(abs(u) < eps) {
    				if(w < -eps) {
    					pp("%.4lf
    ", 0);
    					return 0;
    				}
    				continue;
    			}
    			p = P(-w / u, 0);
    		} else p = P(0, -w / v);
    		b[++ b0] = L(p, P(v, -u));
    	}
    	db s1 = solve(), s2 = qry(a, n);
    	pp("%.4lf
    ", s1 / s2);
    }
    
  • 相关阅读:
    Neutron 理解 (1): Neutron 所实现的虚拟化网络 [How Netruon Virtualizes Network]
    openstack里面的Provider network 和 Tenant network 的区别
    Openstack网络相关概念比较复杂,经常使人混淆,本文进行相关说明。
    OpenStack 网络:Neutron 初探
    openstack 网络架构 nova-network + neutron
    Java 性能测试的四项原则
    微信公众号开发之微信买单
    微信公众号开发之如何使用JSSDK
    微信公众号开发之如何一键导出微信所有用户信息到Excel
    [内核驱动] 链表LIST_ENTRY的操作(转)
  • 原文地址:https://www.cnblogs.com/coldchair/p/13055141.html
Copyright © 2011-2022 走看看