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("\n")
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\n", 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\n", s1 / s2);
}
posted @ 2020-06-06 16:16  Cold_Chair  阅读(192)  评论(0编辑  收藏  举报