概率可以用面积比来算
2026-01-18 15:22:55
发布于:湖南
首先要意识到概率可以用面积比来算
P=可选区域面积/凸多边形总面积
发现每条边是独立的,可以拿每条边和起始边比较
在这里插入图片描述
设A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),P(x,y)
注:以下线段均为向量
AB=(x2−x1,y2−y1),CD=(x4−x3,y4−y3)
AP=(x−x1,y−y1),CP=(x−x3,y−y3)
S
ΔABP
<S
ΔCDP
可得
AB×AP<CD×CP
代入
(x2−x1)(y−y1)−(y2−y1)(x−x1)<(x4−x3)(y−y3)−(y4−y3)(x−x3)
展开
(x2−x1+x3−x4)y−(y2−y1−y4+y3)x+(−x2y1+x1y2+x4y3−x3y4)<0
Ax+By+C<0
By<−Ax−C
关于实现方面我和楼上的大佬不太一样,他们的边是用一个点+一个向量表示的
我的是用两个点表示的,所以在确定第一个点的时候,可以直接代入x或y的零点,而第二点必须要用第一个确定的点加上一个向量后的点来表示
code:
#include<bits/stdc++.h>
#define db double
#define N 800005
using namespace std;
const db eps = 1e-14;
struct A {
db x, y;
A operator + (const A &a) const {
return (A){x + a.x, y + a.y};
}
A operator - (const A &a) const {
return (A){x - a.x, y - a.y};
}
A operator * (const double &a) const {
return (A){x * a, y * a};
}
} a[N];
A pt(db x, db y) {
return A{x, y};
}
struct LI {
A a, b;
double k;
LI() {}
LI(A x, A y) {
a = x, b = y;
A d = b - a;
k = atan2(d.y, d.x);//算两个点连线的斜率
}
} ls[N], L[N];
db dis(A x) {
return sqrt(x.x * x.x + x.y * x.y);
}
db cha(A x, A y) {
return x.x * y.y - x.y * y.x;
}
int check(A a, LI b) {
return cha(a - b.a, b.b - a) > eps;
}
A getp(LI a, LI b) {
double k = cha(b.b - b.a, a.a - b.a) / cha(a.b - a.a, b.b - b.a);
return a.a + (a.b - a.a) * k;
}
int cmp(LI x, LI y) {
if(fabs(x.k - y.k) > eps) return x.k < y.k;
return cha(y.a - x.a, x.b - y.a) > eps;
}
int n, q[N];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%lf%lf", &a[i].x, &a[i].y);
a[n + 1] = a[1];
double anss = 0;
for(int i = 1; i <= n; i ) {
anss += cha(a[i] - a[1], a[i + 1] - a[1]);//计算凸包总面积
L[i] = LI(a[i], a[i + 1]);
}
int m = n;
for(int i = 2; i <= m; i ) { //Ax + By + C < 0
db A = a[1].y - a[2].y + a[i + 1].y - a[i].y;
db B = a[2].x - a[1].x + a[i].x - a[i + 1].x;
db C = - a[2].x * a[1].y + a[1].x * a[2].y + a[i + 1].x * a[i].y - a[i].x * a[i + 1].y;
if(fabs(B) < eps) L[ n] = LI(pt(- C / A, 0), pt(- C / A - B, A));
else L[ n] = LI(pt(0, - C / B), pt(- B, - C / B + A));//加入直线
}
sort(L + 1, L + 1 + n, cmp);
int sz = 0; ls[++ sz] = L[1];
for(int i = 2; i <= n; i ++)//去重
if(L[i].k != L[i - 1].k) ls[++ sz] = L[i];
for(int i = 1; i <= sz; i ++) L[i] = ls[i];
n = sz;
//下面是半平面交板子
int l = 1, r = 0;
for(int i = 1; i <= n; i ++) {
while(l < r && check(a[r], L[i])) r --;
while(l < r && check(a[l + 1], L[i])) l ++;
q[++ r] = i;
if(l < r) a[r] = getp(L[q[r - 1]], L[q[r]]);
}
while(l < r && check(a[r], L[q[l]])) r --;
while(l < r && check(a[l + 1], L[q[r]])) l ++;
a[l] = getp(L[q[r]], L[q[l]]);
double ans = 0;
for(int i = l + 1; i < r; i ++) ans += cha(a[i] - a[l], a[i + 1] - a[l]);
printf("%.4lf", ans / anss);
return 0;
}
要学会转换,敢去推式子
这里空空如也







有帮助,赞一个