【bzoj4445 scoi2015】小凸想跑步
题目描述
小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏。
操场是个凸 n 边形, n 个顶点按照逆时针从 0 ∼ n−1 编号。现在小凸随机站在操场中的某个位置,标记为 p 点。将 p点与 n 个顶点各连一条边,形成 n 个三角形。如果这时 p 点, 0 号点, 1 号点形成的三角形的面 积是 n 个三角形中最小的一个,小凸则认为这是一次正确站位。
现在小凸想知道他一次站位正确的概率是多少。
输入输出格式
输入格式:
第 1 行包含 1 个整数 n , 表示操场的顶点数和游戏的次数。
接下来有 n 行,每行包含 2 个整数 xi,yi ,表示顶点的坐标。
输入保证按逆时针顺序输入点,所有点保证构成一个凸多边形。所有点保证不存在三点共线。
输出格式:
输出 1 个数,正确站位的概率,保留 4 位小数。
说明
对于 30 % 的数据, 3≤n≤4,0≤x,y≤10
对于 100 % 的数据, 3≤n≤105,−109≤x,y≤109
题意:已经很清楚了!
题解:
①你可以设坐标为x,y画一下柿子可以做,网上这类做法主流;
②下面是大米兔的非主流做法:
肯定是用合法的面积/总面积,AB是P0P1的话,合法的应该是OE分割的的靠近
AB的半部分,如果求出所有的OE就可以求出合法的面积;OE是什么呢?定义是
在OE上的任意一点P,$S_{PDC}=S_{PAB}$,E的方向可以直接由A'D'的中点
获得,结合交点O可求出OE,这样复杂度OK;实现也是半平面交而已;
③注意n变形的n条边也要加进去!
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const double eps = 1e-20; 7 const int N=200010; 8 typedef long double lf; 9 int n,m,tot; 10 char gc(){ 11 static char *p1,*p2,s[1000000]; 12 if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin); 13 return (p1==p2)?EOF:*p1++; 14 } 15 int rd(){ 16 int x=0,f=1; char c=gc(); 17 while(c<'0'||c>'9') {if(c=='-') f=-1;c=gc();} 18 while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-'0';c=gc();} 19 return x*f; 20 } 21 int dcmp(lf x){return fabs(x)<eps?0:x<0?-1:1;/*x==0?0:x<0?-1:1;*/} 22 struct point{lf x,y;point(){};point(lf x,lf y):x(x),y(y){};}p[N],py[N]; 23 struct line{point A,B; lf ang;line(){}line(point A,point B):A(A),B(B){ang=atan2(B.y-A.y,B.x-A.x);}}hp[N],l[N]; 24 point operator -(const point&A,const point&B){return point(A.x-B.x,A.y-B.y);} 25 point operator +(const point&A,const point&B){return point(A.x+B.x,A.y+B.y);}/// 26 lf operator *(const point&A,const point&B){return A.x*B.y-A.y*B.x;} 27 lf operator ^(const point&A,const point&B){return A.x*B.x+A.y*B.y;} 28 point operator *(const point&A,lf t){return point(A.x*t,A.y*t);} 29 point operator /(const point&A,lf t){return point(A.x/t,A.y/t);} 30 bool operator <(const line&l1,const line&l2){ 31 int d = dcmp(l1.ang-l2.ang); 32 return (!d)?(dcmp((l1.B-l1.A)*(l2.A-l1.A))<0):(d<0); 33 }/// 34 point inter(line l1, line l2){ 35 if(!dcmp(l1.ang-l2.ang)) return (l1.A+l2.A)/2; 36 lf t,k1,k2; 37 k1 = (l2.B-l2.A)*(l1.A-l2.A); 38 k2 = (l1.B-l1.A)*(l2.B-l2.A); 39 t = k1 / k2; 40 return l1.A + (l1.B-l1.A)*t; 41 }////// 42 bool onleft(line l1,line l2,line l){ 43 point ip = inter(l1,l2); 44 return dcmp((l.B-l.A)*(ip-l.A))>0; 45 }// 46 lf len(point A){return sqrt(A.x*A.x+A.y*A.y);} 47 void half(){/// 48 sort(l+1,l+tot+1); 49 int tmp = tot,tot = 0,L=0,R=0; 50 for(int i=1;i<=tmp;i++){if(i==1||dcmp(l[i-1].ang-l[i].ang)) l[++tot]=l[i];} 51 hp[++R] = l[1]; hp[++R] = l[2]; 52 for(int i=3;i<=tot;i++){ 53 while(L<R-1&&!onleft(hp[R],hp[R-1],l[i])) R--; 54 while(L<R-1&&!onleft(hp[L+1],hp[L+2],l[i])) L++; 55 hp[++R] = l[i]; 56 } 57 while(L<R-1&&!onleft(hp[R],hp[R-1],hp[L+1])) R--; hp[++R] = hp[L+1]; 58 m=0;for(int i=L+1;i<R;i++) py[++m]=inter(hp[i],hp[i+1]); 59 } 60 point calc(point A,point B){return (A+B)/2;} 61 int main() 62 { freopen("bzoj4445.in","r",stdin); 63 freopen("bzoj4445.out","w",stdout); 64 n=rd(); 65 for(int i=1;i<=n;i++) p[i].x=rd(),p[i].y=rd(); p[n+1] = p[1]; 66 for(int i=1;i<=n;i++) l[++tot] = line(p[i],p[i+1]);/// 67 for(int i=2;i<=n;i++){ 68 point ip = inter(line(p[i+1],p[i]),line(p[1],p[2])),v; 69 if(dcmp((p[2]-p[1])*(p[i+1]-p[i]))>=0) 70 v=calc(p[1]-p[2],p[i+1]-p[i]),l[++tot]=line(ip,ip+v); 71 else v=calc(p[2]-p[1],p[i]-p[i+1]),l[++tot]=line(ip+v,ip);////// 72 //printf("%d %.4lf %.4lf\n",i,v.x,v.y); 73 } 74 half(); 75 lf ansA = 0,ansB = 0; 76 for(int i=2;i<m;i++) ansA+=(py[i+1]-py[i])*(py[i]-py[1]); ansA = fabs(ansA); 77 for(int i=2;i<n;i++) ansB+=(p[i+1]-p[i])*(p[i]-p[1]); ansB = fabs(ansB);// 78 printf("%.4Lf",ansA/ansB); 79 return 0; 80 }//by tkys_Austin;