zoukankan      html  css  js  c++  java
  • BZOJ 4445 [Scoi2015]小凸想跑步:半平面交

    传送门

    题意

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

    操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号。

    现在小凸随机站在操场中的某个位置,标记为 $ P $ 点。将 $ P $ 点与 $ n $ 个顶点各连一条边,形成 $ n $ 个三角形。如果这时 $ (P, P_0, P_1) $ 形成的三角形的面积是 $ n $ 个三角形中最小的一个,小凸则认为这是一次正确站位。

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

    题解

    对于一次正确站位 $ P $ 来说,要满足两个条件:

    1. $ area(P, P_0. P_1) < area(P, P_i, P_{i+1}) quad (1 leq i lt n-1) $,其中 $ area $ 表示三角形面积。
    2. $ P $ 在多边形内部。

    对于条件1来说,将面积转化成叉积形式:

    [overrightarrow{PP_0} imes overrightarrow{PP_1} < overrightarrow{PP_i} imes overrightarrow{PP_{i+1}} quad (1 leq i lt n-1) ]

    然后再将向量拆开,整理得:

    [(-y_1+y_0+y_{i+1}-y_i)x + (-x_0+x_1+x_i-x_{i+1})y + (x_0y_1-x_1y_0-x_iy_{i+1}+x_{i+1}y_i) < 0 ]

    这样就得到了 $ n $ 个以一般式 $ Ax+By+C<0 $ 的形式表示的半平面。

    另外对于条件2来说,也是 $ n-1 $ 个半平面。

    所以总共就有了 $ 2n-1 $ 个半平面,跑一边半平面交,就求出了正确站位的总面积 $ S_{right} $ 。

    设凸多边形的面积为 $ S $ ,则答案就是 $ dfrac{S_{right}}{S} $ 。

    AC Code

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #define MAX_N 200005
    #define EPS 1e-10
    #define eq(x,y) (fabs((x)-(y))<EPS)
    
    using namespace std;
    
    struct Coor
    {
    	double x,y;
    	Coor(double _x,double _y) { x=_x,y=_y; }
    	Coor(){}
    	friend Coor operator + (const Coor &a,const Coor &b)
    	{
    		return Coor(a.x+b.x,a.y+b.y);
    	}
    	friend Coor operator - (const Coor &a,const Coor &b)
    	{
    		return Coor(a.x-b.x,a.y-b.y);
    	}
    	friend Coor operator * (const Coor &a,double b)
    	{
    		return Coor(a.x*b,a.y*b);
    	}
    	friend Coor operator / (const Coor &a,double b)
    	{
    		return Coor(a.x/b,a.y/b);
    	}
    	friend double len(Coor a,Coor b)
    	{
    		return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    	}
    	friend double dot(Coor a,Coor b)
    	{
    		return a.x*b.x+a.y*b.y;
    	}
    	friend double cross(Coor a,Coor b)
    	{
    		return a.x*b.y-a.y*b.x;
    	}
    	friend double area(Coor a,Coor b,Coor c)
    	{
    		return fabs(cross(b-a,c-a))/2.0;
    	}
    };
    
    struct Line
    {
    	Coor a,b;
    	double s;
    	Line(Coor _a,Coor _b)
    	{
    		a=_a,b=_b;
    		s=atan2(b.y-a.y,b.x-a.x);
    	}
    	Line(){}
    	friend bool operator < (const Line &l1,const Line &l2)
    	{
    		return l1.s!=l2.s ? l1.s<l2.s : cross(l1.b-l1.a,l2.b-l1.a)<0;
    	}
    	friend Coor inter(Line l1,Line l2)
    	{
    		Coor x=l1.b-l1.a,y=l2.b-l2.a,u=l1.a-l2.a;
    		Coor ans=l1.a+x*(cross(y,u)/cross(x,y));
    		return ans;
    	}
    	friend bool onlef(Coor p,Line l)
    	{
    		return cross(l.b-l.a,p-l.b)>0;
    	}
    };
    
    int n,tot=0,cnt=0;
    double sum=0,ans=0;
    Coor p[MAX_N];
    Coor a[MAX_N];
    Line l[MAX_N];
    Line q[MAX_N];
    
    void read()
    {
    	scanf("%d",&n);
    	for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
    	p[n]=p[0];
    	for(int i=1;i<n-1;i++) sum+=area(p[0],p[i],p[i+1]);
    }
    
    void build()
    {
    	for(int i=1;i<n;i++)
    	{
    		double a=-p[1].y+p[0].y+p[i+1].y-p[i].y;
    		double b=-p[0].x+p[1].x+p[i].x-p[i+1].x;
    		double c=p[0].x*p[1].y-p[1].x*p[0].y-p[i].x*p[i+1].y+p[i+1].x*p[i].y;
    		Coor u=(eq(b,0) ? Coor(-c/a,0) : Coor(0,-c/b)),v(-b,a);
    		l[++tot]=Line(u,u+v);
    	}
    	for(int i=0;i<n;i++) l[++tot]=Line(p[i],p[i+1]);
    }
    
    void hpi()
    {
    	sort(l+1,l+1+tot);
    	int L=1,R=0,now=0;
    	for(int i=1;i<=tot;i++) if(i==1 || l[i].s!=l[now].s) l[++now]=l[i];
    	tot=now,q[++R]=l[1],q[++R]=l[2];
    	for(int i=3;i<=tot;i++)
    	{
    		while(L<R && !onlef(inter(q[R],q[R-1]),l[i])) R--;
    		while(L<R && !onlef(inter(q[L],q[L+1]),l[i])) L++;
    		q[++R]=l[i];
    	}
    	while(L<R && !onlef(inter(q[R],q[R-1]),q[L])) R--;
    	while(L<R && !onlef(inter(q[L],q[L+1]),q[R])) L++;
    	q[R+1]=q[L];
    	for(int i=L;i<=R;i++) a[++cnt]=inter(q[i],q[i+1]);
    	for(int i=2;i<cnt;i++) ans+=area(a[1],a[i],a[i+1]);
    }
    
    void work()
    {
    	build();
    	hpi();
    	printf("%.4f
    ",ans/sum);
    }
    
    int main()
    {
    	read();
    	work();
    }
    
  • 相关阅读:
    [Swift实际操作]七、常见概念-(5)使用NSString对字符串进行各种操作
    [Swift]LeetCode326. 3的幂 | Power of Three
    [Swift]LeetCode303. 区域和检索
    [Swift]LeetCode292. Nim游戏 | Nim Game
    [Swift]LeetCode290. 单词模式 | Word Pattern
    SpringMVC框架中的异常解析器-ExceptionHandler和HandlerExceptionResolver
    一个Web报表项目的性能分析和优化实践(七):性能监测工具JavaMelody
    一个Web报表项目的性能分析和优化实践(七):性能监测工具JavaMelody
    百度Echarts-免费的商业产品图表库
    百度Echarts-免费的商业产品图表库
  • 原文地址:https://www.cnblogs.com/Leohh/p/9195384.html
Copyright © 2011-2022 走看看