zoukankan      html  css  js  c++  java
  • [SCOI2015]小凸想跑步

    题目描述

    小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏。

    操场是个凸 n 边形, nn 个顶点按照逆时针从 0 ∼n1 编号。现在小凸随机站在操场中的某个位置,标记为p点。将 p 点与 n个顶点各连一条边,形成 n个三角形。如果这时p 点, 0号点, 1号点形成的三角形的面 积是 n个三角形中最小的一个,小凸则认为这是一次正确站位。

    现在小凸想知道他一次站位正确的概率是多少。

    题解

    我们其实是要找到一个p点,使得pp0*pp1<=ppi*ppi+1.

    然后我们把上面的式子展开,然后化简,这个不难就是挺麻烦的。

    最后得到了Ax+By+C<=0的形式,然后可以用(-1e9,y1)(1e9,y2)这条直线来描述这个限制,再加上凸多边形的限制,跑个半平面交就好了。

    注意:要特判A或B=0的情况。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #define N 200009
    #define double long double
    #define eq(x,y) (fabs((x)-(y))<eps)
    using namespace std;
    const double eps=1e-15;
    int n,top,tot;
    double x[N],y[N],s,S;
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct point{
        double x,y;
        point(double xx=0,double yy=0){x=xx;y=yy;}
        inline point operator +(const point &b)const{return point{x+b.x,y+b.y};} 
        inline point operator -(const point &b)const{return point{x-b.x,y-b.y};}
        inline double operator *(const point &b)const{return x*b.y-y*b.x;}
        inline point operator *(const double &b)const{return point{x*b,y*b};} 
    }p[N];
    struct line{
        point x,y;double ang;
        line(double x1=0,double x2=0,double x3=0,double x4=0){x.x=x1;x.y=x2;y.x=x3;y.y=x4;}
         bool operator <(const line &b)const{
            if(fabs(ang-b.ang)<eps)return (y-x)*(b.x-x)<eps; 
            else return ang<b.ang;
        }
    }a[N],l[N],q[N];
    inline bool left(point a,line b){return (a-b.x)*(b.y-b.x)>-eps;}
    inline point jiao(line a,line b){return b.x+(b.y-b.x)*(((b.x-a.x)*(a.y-a.x))/((a.y-a.x)*(b.y-b.x)));}
    int main(){
        n=rd();
        for(int i=0;i<n;++i){
            x[i]=rd(),y[i]=rd();
            if(i)l[++top]=line(x[i-1],y[i-1],x[i],y[i]);
        }
        l[++top]=line(x[n-1],y[n-1],x[0],y[0]);
        for(int i=2;i<n;++i)S+=(point(x[i],y[i])-point(x[0],y[0]))*(point{x[i-1],y[i-1]}-point{x[0],y[0]})/2;S=fabs(S);
        x[n]=x[0];y[n]=y[0];
        for(int i=1;i<n;++i){
            double a=-y[1]+y[0]+y[i+1]-y[i],b=-x[0]+x[1]+x[i]-x[i+1],c=x[0]*y[1]-x[1]*y[0]-x[i]*y[i+1]+x[i+1]*y[i];
            if(fabs(b)<eps){
                if(fabs(a)<eps){puts("0.0000");return 0;}
                double xf=-c/a,xs=xf,yf=0,ys=1e15;
                if(a<0)l[++top]=line(xs,ys,xf,yf);
                else l[++top]=line(xf,yf,xs,ys);
            }
            else{
               double xf=-1e11,xs=1e11,yf=(-c-a*xf)/b,ys=(-c-a*xs)/b;
               if(b>=0){l[++top]=line(xs,ys,xf,yf);
               }else l[++top]=line(xf,yf,xs,ys);
            }
        }
        for(int i=1;i<=top;++i)l[i].ang=atan2(l[i].y.y-l[i].x.y,l[i].y.x-l[i].x.x);
        sort(l+1,l+top+1);
        for(int i=1;i<=top;++i)if(i==1||fabs(l[i].ang-l[i-1].ang)>eps)a[++tot]=l[i];
        int h=1,t=2;q[1]=a[1];q[2]=a[2];p[1]=jiao(a[1],a[2]);
        for(int i=3;i<=tot;++i){
            while(h<t&&left(p[t-1],a[i]))t--;
            while(h<t&&left(p[h],a[i]))h++;
            q[++t]=a[i];p[t-1]=jiao(q[t-1],q[t]);
        }
        while(h<t&&left(p[h],q[t]))h++;
        while(h<t&&left(p[t-1],q[h]))t--;
        p[t]=jiao(q[t],q[h]);
        for(int i=h+2;i<=t;++i)s+=(p[i]-p[h])*(p[i-1]-p[h])/2;s=fabs(s);
        printf("%.4LF",s/S);
        return 0;
    }
  • 相关阅读:
    Linux 之 Memcached
    Linux 之 MySQL主从同步
    Linux 之 rsync实现服务器的文件同步
    A.01.03-模块的输入—模拟量输入
    A.01.02—模块的输入—高端输入
    A.01.01—模块的输入—低端输入
    复位电路
    边沿触发和电平触发的区别
    深入理解傅里叶变换
    电压跟随器
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10426217.html
Copyright © 2011-2022 走看看