小凸想跑步

来源:互联网 发布:食品生产许可证淘宝 编辑:程序博客网 时间:2024/05/17 03:13

小凸想跑步

时间限制: 1 Sec 内存限制: 128 MB

题目描述
小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏。
操场是个凸n边形,n个顶点按照逆时针从0 ~ n-1编号。现在小凸随机站在操场的某个位置,标记为p点。将p点与n个顶点各连一条边,形成n个三角形。如果这时p点,0号点,1号点形成的三角形的面积是n个三角形中最小的一个,小凸则认为这是一次正确站位。
现在小凸想知道他一次站位正确的概率是多少。

输入
第1行包含1个整数n,表示操场的顶点数和游戏的次数。
接下来有n行,每行包含2个整数xi,yi,表示顶点的坐标。
输入保证按逆时针顺序输入点,所有点保证构成一个凸多边形。所有点保证不存在三点共线。

输出
输出1个数,正确站位的概率,保留4个小数。

样例输入
5
1 8
0 7
0 0
8 0
8 8

样例输出
0.6316

数据范围
对于30%的数据,3≤n≤4,0≤x,y≤10
对于100%的数据,3≤n≤105,-109≤x,y≤109

来源
SCOI 2015 Day1

题解

对于每一条边,我们可以解一个不等式得到以它为底的三角形面积大于以01号点连边为底的三角形的范围,由此可以得到N个半平面,然后求半平面角即可。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<algorithm>#define N 100010#define eps 1e-7using namespace std;int n,tot;double ans1,ans2;struct point{  double x,y;  point operator+(const point &p)  const{return (point){x+p.x,y+p.y};}  point operator-(const point &p)  const{return (point){x-p.x,y-p.y};}  point operator*(const double &num)  const{return (point){x*num,y*num};}  double operator^(const point &p)  const{return x*p.y-p.x*y;}}t[N],p[N*2];struct node{  point p,v;double ang;  bool operator<(const node &x)  const{return ang<x.ang||(ang==x.ang&&(v^(x.p-p))<eps);}}s[N*2],q[N*2];bool pd(node a,point b){return (a.v^(b-a.p))<-eps;}double get_ang(point p){return atan2(p.y,p.x);}point get_jd(node a,node b){  point x=a.p-b.p;  double t=(b.v^x)/(a.v^b.v);  return a.p+a.v*t;}void solve(){  sort(s+1,s+n+1);tot=1;  for(int i=2;i<=n;i++)    if(fabs(s[i].ang-s[i-1].ang)>eps)s[++tot]=s[i];  int l=1,r=2;q[1]=s[1];q[2]=s[2];n=tot;  for(int i=3;i<=n;i++)  {    while(l<r&&pd(s[i],get_jd(q[r],q[r-1])))r--;    while(l<r&&pd(s[i],get_jd(q[l],q[l+1])))l++;    q[++r]=s[i];  }  while(l<r&&pd(q[l],get_jd(q[r],q[r-1])))r--;  while(l<r&&pd(q[r],get_jd(q[l],q[l+1])))l++;  if(r-l<=1)return;  q[r+1]=q[l];tot=0;  for(int i=l;i<=r;i++)p[++tot]=get_jd(q[i],q[i+1]);  p[tot+1]=p[1];  for(int i=1;i<=tot;i++)ans2+=fabs((p[i]-p[1])^(p[i+1]-p[1]));}void prepare(){  double X1=t[1].x,Y1=t[1].y;  double X2=t[2].x,Y2=t[2].y;  for(int i=2;i<=n;i++)  {    double X3=t[i].x,Y3=t[i].y;    double X4=t[i+1].x,Y4=t[i+1].y;    double a=Y1-Y2-Y3+Y4,b=X2-X1-X4+X3;    double c=X3*Y4-X4*Y3+X2*Y1-X1*Y2;    double p1,p2,p3,p4;    if(fabs(a)<eps){p1=0,p2=c/b,p3=1,p4=c/b;if(b>0)swap(p1,p3),swap(p2,p4);}    else if(fabs(b)<eps){p1=c/a,p2=0,p3=c/a,p4=1;if(a<0)swap(p1,p3),swap(p2,p4);}         else if(b<0)p1=0,p2=c/b,p3=1,p4=c/b-a/b;              else p1=1,p2=c/b-a/b,p3=0,p4=c/b;    point X1=(point){p1,p2},X2=(point){p3-p1,p4-p2};    s[i]=(node){X1,X2,get_ang(X2)};  }  s[1]=(node){t[1],t[2]-t[1],get_ang(t[2]-t[1])};} int main(){  scanf("%d",&n);  for(int i=1;i<=n;i++)    scanf("%lf%lf",&t[i].x,&t[i].y);t[n+1]=t[1];  for(int i=1;i<=n;i++)ans1+=((t[i]-t[1])^(t[i+1]-t[1]));  prepare();solve();  printf("%.4lf",ans2/ans1);  return 0;}
0 0
原创粉丝点击