loj2008 「SCOI2015」小凸想跑步

OI 数学
文章目录

列出面积的不等式,化简发现是线性规划那种形式,用半平面交做。

注意限制点在多边形内哦。

loj 这题卡精度……bzoj不卡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, cnt, tot;
const long double eps=1e-15;
struct Point{
long double x, y;
Point(long double u=0.0, long double v=0.0){
x = u; y = v;
}
Point operator+(const Point &u)const{
return Point(x+u.x, y+u.y);
}
Point operator-(const Point &u)const{
return Point(x-u.x, y-u.y);
}
long double crs(const Point &u)const{
return x*u.y-y*u.x;
}
}pt[100005], a[200005];
Point operator*(long double a, Point b){
return Point(a*b.x, a*b.y);
}
struct Line{
Point x, y;
long double ang;
Line(){}
Line(Point u, Point v){
x = u; y = v;
ang = atan2(v.y, v.x);
}
}l[200005], d[200005];
bool cmp(Line u, Line v){
if(fabs(u.ang-v.ang)>=eps) return u.ang<v.ang;
return u.y.crs(v.x+v.y-u.x)>eps;
}
Point inter(Line u, Line v){
Point a=u.x, b=a+u.y, c=v.x, d=c+v.y;
long double bil=(c-a).crs(d-a)/((c-a).crs(d-a)+(d-b).crs(c-b));
return a+bil*u.y;
}
bool isLeft(Point u, Line v){
return v.y.crs(u-v.x)>eps;
}
void halfPlaneIntersection(){
sort(l+1, l+1+cnt, cmp);
for(int i=1; i<=cnt; i++){
if(i==1 || fabs(l[i].ang-l[i-1].ang)>eps) tot++;
l[tot] = l[i];
}
cnt = tot; tot = 0;
int ll=1, rr=0;
d[++rr] = l[1]; d[++rr] = l[2];
for(int i=3; i<=cnt; i++){
while(ll<rr && !isLeft(inter(d[rr-1], d[rr]), l[i])) rr--;
while(ll<rr && !isLeft(inter(d[ll+1], d[ll]), l[i])) ll++;
d[++rr] = l[i];
}
while(ll<rr && !isLeft(inter(d[rr-1], d[rr]), d[ll])) rr--;
while(ll<rr && !isLeft(inter(d[ll+1], d[ll]), d[rr])) ll++;
d[rr+1] = d[ll];
for(int i=ll; i<=rr; i++)
a[tot++] = inter(d[i], d[i+1]);
}
long double getArea(Point a[], int n){
long double re=0;
if(n<3) return 0;
for(int i=0; i<n; i++)
re += a[i].crs(a[i+1]);
return re/2;
}
int main(){
cin>>n;
for(int i=0; i<n; i++)
scanf("%Lf %Lf", &pt[i].x, &pt[i].y);
pt[n] = pt[0];
for(int i=0; i<n; i++)
l[++cnt] = (Line){pt[i], pt[i+1]-pt[i]};
for(int i=1; i<n; i++){
long double A=pt[0].y-pt[1].y-pt[i].y+pt[i+1].y;
long double B=pt[1].x-pt[0].x-pt[i+1].x+pt[i].x;
long double C=-pt[1].x*pt[0].y+pt[0].x*pt[1].y+pt[i+1].x*pt[i].y-pt[i+1].y*pt[i].x;
Point o;
if(fabs(B)>=eps) o = Point(0.0, -C/B);
else o = Point(-C/A, 0.0);
l[++cnt] = Line(o, Point(-B, A));
}
halfPlaneIntersection();
a[tot] = a[0];
printf("%.4Lf\n", getArea(a, tot)/getArea(pt, n));
return 0;
}