传送门

题意

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

操场是个凸 $ 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. 被Chrome下的remove闪了一下腰

    有用户反映说购物车删除不了东西,于是有了下面的测试. 浏览器:ie7 ie8 ie9 chrome 代码: <a href="javascript:" onclick=&qu ...

  2. Spring4学习笔记-AOP(基于配置文件的方式)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://shamrock.blog.51cto.com/2079212/1557743 引 ...

  3. 原!mysql5.6 存储过程 批量建表

    由于业务需求,需要按天分表,因此写了个存储过程,根据时间生成表. 根据createTime 的时间,以及 while循环的变量设置范围,生成该指定日期及之后的多张表. BEGIN ); ); ; '; ...

  4. 003-主流区块链技术特点及Hyperledger Fabric V1.0版本特点

    一.Hyperledger fabric V1.0 架构 1.逻辑架构: 2.区块链网络 3.运行时架构 二.架构总结 1.架构要点 分拆Peer的功能,将Blockchain的数据维护和共识服务进行 ...

  5. kotlin写的几个小例子

    Kotlin-AdapterDemo kotlin语言下BaseAdapter,ArrayAdapter,SimpleAdapter,SimpleCursorAdapter四种适配器的示例 工具and ...

  6. Mysql学习笔记—视图

    1.什么是视图 视图(View)是一种虚拟存在的表.其内容与真实的表相似,包含一系列带有名称的列和行数据.但是视图并不在数据库中以存储的数据的形式存在.行和列的数据来自定义视图时查询所引用的基本表,并 ...

  7. 解读tensorflow之rnn 的示例 ptb_word_lm.py

    这两天想搞清楚用tensorflow来实现rnn/lstm如何做,但是google了半天,发现tf在rnn方面的实现代码或者教程都太少了,仅有的几个教程讲的又过于简单.没办法,只能亲自动手一步步研究官 ...

  8. 枢轴点(Pivot Point)系统

    Pivot Point是日内交易方法,非常简单实用,是一套非常“单纯”的阻力支持体系,大概是10年前一个做期货的高手发明的方法,至今已经广泛的用在股票.期货.国债.指数等高成交量的商品上.经典的Piv ...

  9. qt下通过socket传送中文

    zz 1.在main函数里我之前就加了一句QTextCodec::setCodecForTr( QTextCodec::codecForLocale() ); 现在再加一句QTextCodec::se ...

  10. Python基础-面向对象1

    class Bar: def fansik(self, name, age): print(name, age) obj = Bar() print(obj.fansik('fanjinbao', 1 ...