UVA - 11722 Joining with Friend

本文解析了一个经典几何概型问题,通过数学建模将两人会面概率转化为平面直角坐标系上的开放区域计算。利用半平面交算法求解交集区域,最后给出了一段C++代码实现,展示如何计算特定条件下的会面概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接

https://odzkskevi.qnssl.com/0675dd7b9a0ce4546b9c81729128719d?v=1537707195

题解

这是一个经典的几何概型,设两人到达的时间分别为 x , y x,y x,y,那么 ∣ x − y ∣ &lt; w |x-y|&lt;w xy<w的时候,两人才能会面,对应到平面直角坐标系中,这个区域是 y = x + w y=x+w y=x+w y = x − w y=x-w y=xw之间的开放区域
基本事件空间是以 ( s 1 , t 1 ) , ( s 1 , t 2 ) , ( s 2 , t 1 ) , ( s 2 , t 2 ) (s_1,t_1),(s_1,t_2),(s_2,t_1),(s_2,t_2) (s1,t1),(s1,t2),(s2,t1),(s2,t2)为四个顶点的矩形
这两个区域求一下交集,其面积与矩形作个比就是答案
求交集可以用半平面交

代码

#include <bits/stdc++.h>
#define maxn 100 
#define eps 1e-8
#define dinf 1e100
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int tot;
struct point
{
    double x, y;
    point(double x, double y):x(x),y(y){}
    point(){}
}pt[maxn], _;
struct vec
{
    point pt; double x, y, th;
    vec(point pt, double x, double y):pt(pt),x(x),y(y){}
    vec(){};
}seg[maxn], q[maxn];
point operator+(point pt, vec v){return point(pt.x+v.x,pt.y+v.y);}
vec operator-(point p1, point p2){return vec(p2,p1.x-p2.x,p1.y-p2.y);}
vec operator+(vec v1, vec v2){return vec(_,v1.x+v2.x,v1.y+v2.y);}
vec operator-(vec v1, vec v2){return vec(_,v1.x-v2.x,v1.y-v2.y);}
double operator*(vec v1, vec v2){return v1.x*v2.y-v2.x*v1.y;}
vec operator*(vec v, double t){return vec(_,v.x*t,v.y*t);}
bool in(point p, vec v){return (p-v.pt)*v<-eps;}
bool operator<(const vec &v1, const vec &v2)
{return fabs(v1.th-v2.th)<eps?in(v1.pt,v2):v1.th<v2.th;}
point inter(vec v1, vec v2)
{
    vec u=v1.pt-v2.pt; double t=v2*u/(v1*v2);
    return v1.pt+v1*t;
}
void hpi()
{
    int l, r, i, x;
    for(i=1;i<=tot;i++)seg[i].th=atan2(seg[i].y,seg[i].x);
    sort(seg+1,seg+tot+1);
    for(x=1,i=2;i<=tot;i++)if(fabs(seg[i].th-seg[i-1].th)>eps)seg[++x]=seg[i];tot=x;
    for(q[l=r=1]=seg[1],i=2;i<=tot;i++)
    {
        while(l<r and !in(inter(q[r],q[r-1]),seg[i]))r--;
        while(l<r and !in(inter(q[l],q[l+1]),seg[i]))l++;
        q[++r]=seg[i];
    }
    while(l<r and !in(inter(q[r],q[r-1]),q[l]))r--;
    while(l<r and !in(inter(q[l],q[l+1]),q[r]))l++;
    pt[tot=1]=inter(q[r],q[l]);
    for(i=l;i<r;i++)pt[++tot]=inter(q[i],q[i+1]);
}
void work()
{
	int i, t1, t2, s1, s2, w;
	double S=0;
	tot=0;
	scanf("%d%d%d%d%d",&s1,&s2,&t1,&t2,&w);
	seg[++tot]=point(s2,t1)-point(s1,t1);
	seg[++tot]=point(s2,t2)-point(s2,t1);
	seg[++tot]=point(s1,t2)-point(s2,t2);
	seg[++tot]=point(s1,t1)-point(s1,t2);
	seg[++tot]=vec(point(w,0),1,1);
	seg[++tot]=vec(point(0,w),-1,-1);
	hpi();
	for(i=2;i<=tot;i++)S+=(pt[i]-pt[1])*(pt[i-1]-pt[1]);
	printf("%.10lf\n",fabs(S)/2/(s2-s1)/(t2-t1)+eps);
}
int main()
{
	int T, kase;
	scanf("%d",&T);
	for(kase=1;kase<=T;kase++)
	{
		printf("Case #%d: ",kase);
		work();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值