传送门

题意

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

操场是个凸 $ 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} \times \overrightarrow{PP_1} < \overrightarrow{PP_i} \times \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\n",ans/sum);
} int main()
{
read();
work();
}

BZOJ 4445 [Scoi2015]小凸想跑步:半平面交的更多相关文章

  1. 4445: [Scoi2015]小凸想跑步 半平面交

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4445 题解: 设点坐标,利用叉积可以解出当p坐标为\((x_p,y_p)\)时,与边i- ...

  2. 【BZOJ4445】[Scoi2015]小凸想跑步 半平面交

    [BZOJ4445][Scoi2015]小凸想跑步 Description 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸n边形,N个顶点按照逆时针从0-n-l编号.现 ...

  3. bzoj 4445 小凸想跑步 - 半平面交

    题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...

  4. bzoj 4445 [SCOI2015] 小凸想跑步

    题目大意:一个凸包,随机一个点使得其与前两个点组成的面积比与其他相邻两个点组成的面积小的概率 根据题意列方程,最后求n条直线的交的面积与原凸包面积的比值 #include<bits/stdc++ ...

  5. 【BZOJ4445】[SCOI2015]小凸想跑步(半平面交)

    [BZOJ4445][SCOI2015]小凸想跑步(半平面交) 题面 BZOJ 洛谷 题解 首先把点给设出来,\(A(x_a,y_a),B(x_b,y_b),C(x_c,y_c),D(x_d,y_d) ...

  6. [SCOI2015]小凸想跑步

    题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n 边形, nn 个顶点按照逆时针从 0 ∼n−1 编号.现在小凸随机站在操场中的某个位置,标记为p点.将 p ...

  7. BZOJ4445: [Scoi2015]小凸想跑步

    裸半平面交. 记得把P0P1表示的半平面加进去,否则点可能在多边形外. #include<bits/stdc++.h> #define N 100009 using namespace s ...

  8. [bzoj4445] [SCOI2015]小凸想跑步 (半平面交)

    题意:凸包上一个点\(p\),使得\(p\)和点\(0,1\)组成的三角形面积最小 用叉积来求: \(p,i,i+1\)组成的三角形面积为: (\(\times\)为叉积) \((p_p-i)\tim ...

  9. 【LuoguP4081】[SCOI2015]小凸想跑步

    题目链接 题意 给你一个凸多边形,求出在其内部选择一个点,这个点与最开始输入的两个点形成的三角形是以该点对凸多边形三角剖分的三角形中面积最小的一个三角形的概率. Sol 答案就是 可行域面积与该凸多边 ...

随机推荐

  1. REDO 的内容:改变向量

    REDO 的内容 ---改变向量 redo的内容并不是sql语句,他是放的一些改变,叫改变向量. 数据库恢复的时候并不是执行sql语句,而是一个物理的过程,是一个数据块的覆盖.是改变数据块的大小. 可 ...

  2. Storm-源码分析-Topology Submit-Executor

    在worker中通过executor/mk-executor worker e, 创建每个executor (defn mk-executor [worker executor-id] (let [e ...

  3. win7下设置smtp的方法

    在win7中开启SMTP服务的方法如下: 1. 首先确定是否开启IIS服务:在运行中输入“inetmgr”,若提示出错,则表明未安装.进入步骤2,否则进入步骤3: 2.打开控制面板->程序-&g ...

  4. java连接elastic search 9300

    java连接elastic search 导入jar包:https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.5/_maven ...

  5. Making the Grade---poj3666(类似离散化+dp)

    题目链接:http://poj.org/problem?id=3666 题意是给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价? ///用dp[i][j]表示 ...

  6. unity里无损实现制定物体bloom

    虽然标题是实现hdr+bloom,但实际感觉更像是控制单个物体bloom https://blog.csdn.net/zsy654321/article/details/80682651

  7. 【MonogDB】The description of index(二) Embedded and document Index

    In this blog, we will talk about another the index which was called "The embedded ". First ...

  8. 简单的 H5 视频推流解决方案

    导语 随着直播平台爆发式增长,直播平台从 PC 端转战移动端,紧跟着直播的潮流,自己学习实现了一套简单的 H5 视频推流的解决方案,下面就给小伙伴们分享一下自己学习过程中的经验. 环境部署 1. 配置 ...

  9. corethink功能模块探索开发(十六)后台搜索功能

    效果图: 代码很简单,就是添加搜索框,搜索字段,在初始化页面查询的时候添加查询条件. 1.添加搜索框 添加到删除按钮后边. ->setSearch('请输入设备名称/MAC/宿舍号', U('i ...

  10. PHP数组的创建

    案例: 仔细看代码,PHP创建数组 <?php $names[0]='Peter'; $names[1]='Minot'; $names[2]='Smith'; echo $names[0].' ...