LOJ #2008. 「SCOI2015」小凸想跑步(半平面交)
题解:
当板题复习写了。
-
枚举要的那个三角形和其它三角形,用叉积列出不等式,不难发现是\(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);
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址