就在这里
概率就是正确站位面积除以凸包面积。
离第一条边比第 k(k>1) 条边更近的充要条件是
化简发现它是一条直线,其中
A=y1−y2−yk+yk+1
B=x2−x1−xk+1+xk
C=x1y2−x2y1−xkyk+1+xk+1yk
然后就上半平面交,求出可行域的面积即可。为了保证在凸包内,将其边也加进去。记得特判 B=0 的情况。
半平面交要求直线交点,我每次求的都是线段的,错了好多次(输出nan让我感到无力。。)。改成另一种适用于直线的写法即可(参考代码,为了证明我甚至用到了全等)。
最后关于有向直线的方向的判定,可以找几个特例来快速判断。
#include
#define Eps 1e-10
#define maxn 200010
using namespace std;
int nn, n, cnt;
struct Point{
double x, y;
Point() {}
Point(double _x, double _y):x(_x), y(_y) {}
friend Point operator + (Point A, Point B){return Point(A.x + B.x, A.y + B.y);}
friend Point operator - (Point A, Point B){return Point(A.x - B.x, A.y - B.y);}
friend Point operator * (double A, Point B){return Point(A * B.x, A * B.y);}
friend Point operator / (Point A, double B){return Point(A.x / B, A.y / B);}
friend double Dot(Point A, Point B){return A.x * B.x + A.y * B.y;}
friend double Det(Point A, Point B){return A.x * B.y - A.y * B.x;}
}Poly[maxn], p[maxn], o[maxn];
struct Line{
Point P, v;
double ang;
Line() {}
Line(Point _P, Point _v):P(_P), v(_v) {ang = atan2(v.y, v.x);}
bool operator < (const Line& l) const{return ang < l.ang;}
}temp, L[maxn], q[maxn];
bool OnLeft(Point A, Line B){
return Det(A - B.P, B.v) < -Eps;
}
Point Cross(Line A, Line B){
Point u = A.P - B.P;
double t = Det(B.v, u) / Det(A.v, B.v);
return A.P + t * A.v;
}//直线相交
bool HPI(){
sort(L+1, L+n+1);
int hh = 0, tt = 0;
q[hh] = L[1];
for(int i = 2; i <= n; i++){
while(hh < tt && !OnLeft(p[tt-1], L[i])) tt --;
while(hh < tt && !OnLeft(p[hh], L[i])) hh ++;
q[++tt] = L[i];
if(fabs(Det(q[tt].v, q[tt-1].v)) < Eps){
tt --;
if(OnLeft(L[i].P, q[tt])) q[tt] = L[i];
}
if(hh < tt) p[tt-1] = Cross(q[tt-1], q[tt]);
}
while(hh < tt && !OnLeft(p[tt-1], q[hh])) tt --;
if(tt - hh <= 1) return false;
p[tt] = Cross(q[tt], q[hh]);
cnt = 0;
for(int i = hh; i <= tt; i++) Poly[++cnt] = p[i];
Poly[cnt+1] = Poly[1];
return true;
}
double GetS(Point *Trista, int m){
double S = 0.0;
for(int i = 1; i <= m; i++)
S += Det(Trista[i], Trista[i+1]);
return S;
}
int main(){
scanf("%d", &nn);
for(int i = 1; i <= nn; i++) scanf("%lf%lf", &o[i].x, &o[i].y);
o[nn+1] = o[1];
for(int i = 1; i <= nn; i++){
L[++n] = Line(o[i], Point(o[i+1] - o[i]));
if(i == 1) continue;
double A = o[1].y - o[2].y - o[i].y + o[i+1].y;
double B = o[2].x - o[1].x + o[i].x - o[i+1].x;
double C = Det(o[1], o[2]) - Det(o[i], o[i+1]);
if(fabs(B) < Eps) temp = Line(Point(-C/A, 0), Point(-B, A));
else temp = Line(Point(0, -C/B), Point(-B, A));
L[++n] = temp;
}
if(HPI()){
double S1 = GetS(o, nn);
double S2 = GetS(Poly, cnt);
printf("%.4lf\n", S2 / S1);
}
else printf("0.0000\n");
return 0;
}