题面

题解

推波柿子:

设点\(A(x_a, y_a), B(x_b, y_b), C(x_c, y_c), D(x_d, y_d), P(x, y)\)

\(\vec{a} = (x_b - x_a, y_b - y_a), \vec{b} = (x_d - x_c, y_d - y_c)\)

\(\overrightarrow{AP} = (x - x_a, y - y_a), \overrightarrow{CP} = (x - x_c, y - y_c)\)

\(\vec{a} \times \overrightarrow{AP} = (x_b - x_a)(y - y_a) - (x_b - y_a)(x - x_a)\)

\(\vec{b} \times \overrightarrow{CP} = (x_d - x_c)(y - y_c) - (y_d - y_c)(x - x_c)\)

由题目,\(\vec{a} \times \overrightarrow{AP} < \vec{b} \times \overrightarrow{CP}\),那么有

\[\begin{aligned}
&(x_b - x_a)(y - y_a) - (x_b - y_a)(x - x_a) < (x_d - x_c)(y - y_c) - (y_d - y_c)(x - x_c) \\
\Rightarrow & (x_b - x_a + x_d - x_c)y - (y_b - y_a - y_d + y_c)x + (y_b x_a - x_b y_a + y_d x_c - x_d y_c) < 0
\end{aligned}
\]

然后这个就是一个裸的半平面交了。

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x)) inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
} const int maxn(200010);
struct point { double x, y; } p[maxn];
struct line { point x, y; double ang; } L[maxn];
typedef point vector; inline vector operator + (const vector &lhs, const vector &rhs)
{ return (vector) {lhs.x + rhs.x, lhs.y + rhs.y}; }
inline vector operator - (const vector &lhs, const vector &rhs)
{ return (vector) {lhs.x - rhs.x, lhs.y - rhs.y}; }
inline vector operator * (const vector &lhs, const double &rhs)
{ return (vector) {lhs.x * rhs, lhs.y * rhs}; }
inline double operator * (const vector &lhs, const vector &rhs)
{ return lhs.x * rhs.x + lhs.y * rhs.y; }
inline double cross(const vector &lhs, const vector &rhs)
{ return lhs.x * rhs.y - lhs.y * rhs.x; }
inline line make_line(const point &x, const point &y)
{ return (line) {x, y, atan2(y.y, y.x)}; }
inline bool operator < (const line &lhs, const line &rhs)
{ return lhs.ang < rhs.ang; }
inline bool isLeft(const point &a, const line &b)
{ return cross(b.y, (a - b.x)) > 0; }
point Intersection(const line &a, const line &b)
{ return a.x + a.y * (cross(b.y, b.x - a.x) / cross(b.y, a.y)); } int n, m;
double Area, ans; void HalfPlane()
{
int l, r = 1; std::sort(L + 1, L + m + 1);
for(RG int i = 2; i <= m; i++)
if(L[i].ang != L[r].ang) L[++r] = L[i];
else if(isLeft(L[i].x, L[r])) L[r] = L[i];
m = r, l = r = 1;
for(RG int i = 2; i <= m; i++)
{
while(l < r && !isLeft(p[r], L[i])) --r;
while(l < r && !isLeft(p[l + 1], L[i])) ++l;
L[++r] = L[i];
if(l < r) p[r] = Intersection(L[r], L[r - 1]);
}
while(l < r && !isLeft(p[r], L[l])) --r;
p[l] = p[r + 1] = Intersection(L[r], L[l]);
for(RG int i = l; i <= r; i++) ans += cross(p[i], p[i + 1]);
ans /= Area;
} int main()
{
n = read();
for(RG int i = 0; i < n; i++)
p[i] = (point) {(double)read(), (double)read()};
p[n] = p[0];
for(RG int i = 0; i < n; i++)
L[++m] = make_line(p[i], p[i + 1] - p[i]),
Area += cross(p[i], p[i + 1]);
for(RG int i = 1; i < n; i++)
{
double a = p[1].x - p[0].x + p[i].x - p[i + 1].x;
double b = p[1].y - p[0].y + p[i].y - p[i + 1].y;
double c = p[1].x * p[0].y + p[i].x * p[i + 1].y
- p[0].x * p[1].y - p[i + 1].x * p[i].y;
if(a) L[++m] = make_line((point) {0, c / a}, (point) {-a, -b});
else if(b) L[++m] = make_line((point) {-c / b, 0}, (point) {0, -b});
}
HalfPlane();
printf("%.4lf\n", ans);
return 0;
}

【SCOI2015】小凸想跑步的更多相关文章

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

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

  2. 【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) ...

  3. [SCOI2015]小凸想跑步

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

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

    传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...

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

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

  6. 洛谷P4250 [SCOI2015]小凸想跑步(半平面交)

    题面 传送门 题解 设\(p\)点坐标为\(x_p,y_p\),那么根据叉积可以算出它与\((i,i+1)\)构成的三角形的面积 为了保证\(p\)与\((0,1)\)构成的面积最小,就相当于它比其它 ...

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

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

  8. BZOJ4445 SCOI2015小凸想跑步(半平面交)

    考虑怎样的点满足条件.设其为(xp,yp),则要满足(x0-xp,y0-yp)×(x1-xp,y1-yp)<=(xi-xp,yi-yp)×(xi+1-xp,yi+1-yp)对任意i成立.拆开式子 ...

  9. 2018.10.15 bzoj4445: [Scoi2015]小凸想跑步(半平面交)

    传送门 话说去年的省选计算几何难度跟前几年比起来根本不能做啊(虽然去年考的时候并没有学过计算几何) 这题就是推个式子然后上半平面交就做完了. 什么? 怎么推式子? 先把题目的概率转换成求出可行区域. ...

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

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

随机推荐

  1. [SQLSERVER] 转移数据库MDF或LDF文件位置的方法,以及重新启动出现无权限的问题

    0. 查看数据库文件名和物理文件名 SELECT name, physical_name AS current_file_location FROM sys.master_files 1. 运行命令 ...

  2. C# RSA 加密

    class Sign_verifySign { #region prepare string to sign. //example format: a=123&b=xxx&c (wit ...

  3. Asp.net Mvc身份验证

    1.安装组件 Microsoft.AspNet.Identity.Core,身份认证核心组件 安装Microsoft.AspNet.Identity.EntityFramework,EF实现身份认证 ...

  4. 【PAT】B1001 害死人不偿命的(3n+1)猜想

    超级简单题 偶数砍掉一半, 奇数乘三加一砍掉一半 #include<stdio.h> int mian(){ int n,step=0; scanf("%d",n); ...

  5. MySQL面试题之死锁

    什么是死锁?锁等待?如何优化这类问题?通过数据库哪些表可以监控? 死锁是指两个或多个事务在同一资源上互相占用,并请求加锁时,而导致的恶性循环现象.当多个事务以不同顺序试图加锁同一资源时,就会产生死锁. ...

  6. rsync远程同步的基本配置与使用

    rsync是一个开源的快速备份工具,可以在不同主机之间镜像同步整个目录树,支持增量备份,保持链接和权限,且采用优化的同步算法,传输前执行压缩,因此非常适用于异地备份,镜像服务器等应用. rsync的官 ...

  7. February 4th, 2018 Week 6th Sunday

    Hope clouds observation. 心怀希望会蒙蔽双眼,影响判断. Almost every of us thinks we would be the master of our liv ...

  8. mybatis隐藏不用的sql

    在mybatis的xml中,选中了不用的sql语句,使用ctrl + shift + / 隐去,,结果是 <where> <if test="dto.startTime ! ...

  9. 团队Alpha博客链接目录

    Dipper团队Alpha博客链接目录 团队Alpha冲刺博客 第一次冲刺 第二次冲刺 第三次冲刺 第四次冲刺 第五次冲刺 第六次冲刺 第七次冲刺 第八次冲刺 第九次冲刺 第十次冲刺 第十一次冲刺 第 ...

  10. String类的常用方法详解

    1:获取字符串的长度length(),下标从1开始 2:将其他类型转换为String类型toStrings() 3:去除字符串首尾的空格trim() 4:分割字符串spilt() 5:比较两个字符串是 ...