bzoj 4445 [SCOI2015] 小凸想跑步

题目大意:一个凸包,随机一个点使得其与前两个点组成的面积比与其他相邻两个点组成的面积小的概率

根据题意列方程,最后求n条直线的交的面积与原凸包面积的比值

  1 #include<bits/stdc++.h>
  2 #define maxn 100010
  3 #define eps 1e-10
  4 using namespace std;
  5 double ans,S1,S2;
  6 struct P{
  7     double x,y;
  8     P(double a=0,double b=0){x=a,y=b;}
  9 };
 10 struct L{
 11     P a,b;
 12     double ang;
 13 };
 14 int sgn(double x){
 15     return (x>eps)-(x<-eps);
 16 }
 17 P operator - (P a,P b){
 18     return P(a.x-b.x,a.y-b.y);
 19 }
 20 double operator * (P a,P b){
 21     return a.x*b.y-a.y*b.x;
 22 }
 23 bool operator < (L a,L b){
 24     if(sgn(a.ang-b.ang)!=0)return a.ang<b.ang;
 25     return (a.a-b.a)*a.b<0;
 26 }
 27 int n;
 28 P s[maxn];
 29 L l[maxn],q[maxn];P p[maxn];
 30 int h,r,tot,cnt;
 31 L get_line(P A,P B,P C,P D){
 32     L l;
 33     double a=-A.y-D.y+B.y+C.y;
 34     double b=-B.x-C.x+A.x+D.x;
 35     double c=-A.x*B.y-D.x*C.y+B.x*A.y+C.x*D.y;
 36     l.b=P(b,-a);
 37     if(sgn(a)!=0)l.a=P(-c/a,0);
 38     else l.a=P(0,-c/b);
 39     return l;
 40 }
 41 void get_line(){
 42     for(int i=2;i<=n;++i)
 43         l[++cnt]=get_line(s[1],s[2],s[i],s[i+1]);
 44     for(int i=1;i<=n;++i){
 45         l[++cnt].a=s[i];
 46         l[cnt].b=s[i+1]-s[i];
 47     }
 48     for(int i=1;i<=cnt;++i)
 49         l[i].ang=atan2(l[i].b.y,l[i].b.x);
 50 }
 51 P inter(L a,L b){
 52     P p=b.a-a.a;
 53     double t=(p*b.b)/(a.b*b.b);
 54     P ans;
 55     ans.x=a.a.x+a.b.x*t;
 56     ans.y=a.a.y+a.b.y*t;
 57     return ans;
 58 }
 59 bool jud(L a,L b,L c){
 60     P p=inter(a,b);
 61     return (p-c.a)*c.b>0;
 62 }
 63 void get_Point(){
 64     sort(l+1,l+cnt+1);tot=1;
 65     for(int i=2;i<=cnt;++i)
 66         if(sgn(l[i].ang-l[i-1].ang)!=0)
 67             l[++tot]=l[i];
 68     cnt=tot;tot=0,h=1;
 69     q[++r]=l[1];q[++r]=l[2];
 70     for(int i=3;i<=cnt;++i){
 71         if(sgn(q[r].b*q[r-1].b)==0)return;
 72         if(sgn(q[h].b*q[h+1].b)==0)return;
 73         while(h<r&&jud(q[r-1],q[r],l[i]))r--;
 74         while(h<r&&jud(q[h+1],q[h],l[i]))h++;
 75         q[++r]=l[i];
 76     }
 77     while(h<r&&jud(q[r-1],q[r],q[h]))r--;
 78     while(h<r&&jud(q[h+1],q[h],q[r]))h++;
 79     q[r+1]=q[h];
 80     for(int i=h;i<=r;++i)
 81         p[++tot]=inter(q[i],q[i+1]);
 82     p[++tot]=p[1];
 83 }
 84 double get_S(P a[],int cnt){
 85     double ans=0;
 86     if(cnt<3)return 0;
 87     for(int i=1;i<cnt;++i){
 88         ans+=a[i]*a[i+1];
 89     }
 90     ans=fabs(ans/2);
 91     return ans;
 92 }
 93 void init(){
 94     scanf("%d",&n);
 95     for(int i=1;i<=n;++i){
 96         int x,y;scanf("%d%d",&x,&y);
 97         s[i].x=x;s[i].y=y;
 98     }
 99     s[n+1]=s[1];
100 }
101 void work(){
102     get_line();
103     get_Point();
104     S1=get_S(s,n+1);
105     S2=get_S(p,tot);
106     ans=S2/S1;
107     printf("%.4lf",ans);
108 }
109 int main(){
110     init();
111     work();
112     return 0;
113 }
View Code
原文地址:https://www.cnblogs.com/117208-/p/5361080.html