UVA 11722 Joining with Friend

来源:互联网 发布:域名买卖赚钱吗 编辑:程序博客网 时间:2024/05/29 02:18

题意:一个人到达的时间为【t1,t2】,另一个人到达为【s1,s2】,到达之后会停留w时间,求两人相遇的概率

思路:可以分情况讨论,求出面积,然后算面积比就好了,然后我用半平面交写了一个。。反正无聊就当练模板 了。。。

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<algorithm>#define inf 0x7ffffffusing namespace std;const double eps=1e-10;int n,k,h,top,bot,dq[1000000];int ln;double t1,t2,s1,s2,w;int pn;double ans;struct P{double x,y;P(){}P(double x,double y):x(x),y(y){}P operator +(P p){return P(x+p.x,y+p.y);}P operator -(P p){return P(x-p.x,y-p.y);}P operator *(double d){return P(x*d,y*d);}double det(P p){return x*p.y-y*p.x;}};P p[1000000];struct Line{P a,b;double angle;}l[1000000];//判断大小函数。int dblcmp(double k){    if(fabs(k)<eps)    return 0;    return k>0?1:-1;}//极角排序,相同的则按靠里面的放前bool cmp(Line a,Line b){    int d=dblcmp(a.angle-b.angle);    if(!d)    return dblcmp((b.a-a.a).det(b.b-a.a))>0;    return d<0;}//求直线a,b的交点函数P in(Line a,Line b){    return a.a+(a.b-a.a)*((b.b-b.a).det(b.a-a.a) / (b.b-b.a).det(a.b-a.a));}//b,c为半平面的顶点的两条直线,若它们的交点在新加入的半平面外,则返回1;bool judge(Line a,Line b,Line c){    P r=in(b,c);    return dblcmp((a.a-r).det(a.b-r))<0;}double getarea(){    double marea=0;    if(pn<3)    marea=0;    //面积计算公式,也可以用叉乘直接算    for(int i=0;i<pn-1;i++)    {        marea+=(p[i].x*p[i+1].y-p[i].y*p[i+1].x);    }    marea+=(p[pn-1].x*p[0].y-p[pn-1].y*p[0].x);    marea=fabs(marea);    marea/=2.0;return marea;}void solve(){int len;    int i,j;    //按极角排序    sort(l,l+ln,cmp);    for(i=0,j=0;i<ln;i++)    {        if(dblcmp(l[i].angle-l[j].angle)>0)  //存在极角相同的则取第一个        l[++j]=l[i];    }    len=j+1;    //dq为双端队列,存线段的编号信息    dq[0]=0;    dq[1]=1;    top=1;    bot=0;    for(i=2;i<len;i++)    {        //若顶端的两条直线的交点在新半平面l[i]外,那么这个顶点就弹出        while(top>bot && judge(l[i],l[dq[top]],l[dq[top-1]])) top--;        //旋转一圈左右,如果底部的交点在新加入的半平面外,底部弹出        while(top>bot && judge(l[i],l[dq[bot]],l[dq[bot+1]])) bot++;        dq[++top]=i;    }    //若顶部的交点不在底部的半平面内,则顶部弹出    while(top>bot && judge(l[dq[bot]],l[dq[top]],l[dq[top-1]])) top--;    //同理若底部的交点不在顶部的半平面内,则底部弹出    while(top>bot && judge(l[dq[top]],l[dq[bot]],l[dq[bot+1]])) bot++;    //底部加入进来,方便计算半平面交成的凸多边形顶点    dq[++top]=dq[bot];    for(pn=0,i=bot;i<top;i++,pn++)    {        p[pn]=in(l[dq[i+1]],l[dq[i]]);    }ans+=getarea();}int main(){int step=1;scanf("%d",&n);while(n--){ans=0;scanf("%lf%lf%lf%lf%lf",&t1,&t2,&s1,&s2,&w);ln=0;l[ln].a.x=t1;l[ln].a.y=s1;l[ln].b.x=t2;l[ln].b.y=s1;l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);ln++;l[ln].a.x=t2;l[ln].a.y=s1;l[ln].b.x=t2;l[ln].b.y=s2;l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);ln++;l[ln].a.x=t2;l[ln].a.y=s2;l[ln].b.x=t1;l[ln].b.y=s2;l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);ln++;l[ln].a.x=t1;l[ln].a.y=s2;l[ln].b.x=t1;l[ln].b.y=s1;l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);ln++;l[ln].a.x=0;l[ln].a.y=-w;l[ln].b.x=w;l[ln].b.y=0;l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);ln++;l[ln].a.x=0;l[ln].a.y=w;l[ln].b.x=-w;l[ln].b.y=0;l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);ln++;solve();ans/=(t2-t1)*(s2-s1);printf("Case #%d: %.8lf\n",step++,ans);}return 0;}


0 0