【SCOI2015】小凸想跑步
题面
题解
推波柿子:

设点\(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}\),那么有
&(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】小凸想跑步的更多相关文章
- 【BZOJ4445】[Scoi2015]小凸想跑步 半平面交
[BZOJ4445][Scoi2015]小凸想跑步 Description 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸n边形,N个顶点按照逆时针从0-n-l编号.现 ...
- 【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) ...
- [SCOI2015]小凸想跑步
题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n 边形, nn 个顶点按照逆时针从 0 ∼n−1 编号.现在小凸随机站在操场中的某个位置,标记为p点.将 p ...
- BZOJ 4445 [Scoi2015]小凸想跑步:半平面交
传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...
- bzoj 4445 [SCOI2015] 小凸想跑步
题目大意:一个凸包,随机一个点使得其与前两个点组成的面积比与其他相邻两个点组成的面积小的概率 根据题意列方程,最后求n条直线的交的面积与原凸包面积的比值 #include<bits/stdc++ ...
- 洛谷P4250 [SCOI2015]小凸想跑步(半平面交)
题面 传送门 题解 设\(p\)点坐标为\(x_p,y_p\),那么根据叉积可以算出它与\((i,i+1)\)构成的三角形的面积 为了保证\(p\)与\((0,1)\)构成的面积最小,就相当于它比其它 ...
- BZOJ4445: [Scoi2015]小凸想跑步
裸半平面交. 记得把P0P1表示的半平面加进去,否则点可能在多边形外. #include<bits/stdc++.h> #define N 100009 using namespace s ...
- BZOJ4445 SCOI2015小凸想跑步(半平面交)
考虑怎样的点满足条件.设其为(xp,yp),则要满足(x0-xp,y0-yp)×(x1-xp,y1-yp)<=(xi-xp,yi-yp)×(xi+1-xp,yi+1-yp)对任意i成立.拆开式子 ...
- 2018.10.15 bzoj4445: [Scoi2015]小凸想跑步(半平面交)
传送门 话说去年的省选计算几何难度跟前几年比起来根本不能做啊(虽然去年考的时候并没有学过计算几何) 这题就是推个式子然后上半平面交就做完了. 什么? 怎么推式子? 先把题目的概率转换成求出可行区域. ...
- [bzoj4445] [SCOI2015]小凸想跑步 (半平面交)
题意:凸包上一个点\(p\),使得\(p\)和点\(0,1\)组成的三角形面积最小 用叉积来求: \(p,i,i+1\)组成的三角形面积为: (\(\times\)为叉积) \((p_p-i)\tim ...
随机推荐
- 浅谈Arrays.asList()方法的使用
首先,该方法是将数组转化为list.有以下几点需要注意: (1)该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean) (2)该方法将数组与列表 ...
- Collections工具类
Collections 是一个操作 Set.List 和 Map 等集合的工具类. Collections 中提供了一系列静态的方法对集合元素进行排序.查询和修改等操作,还提供了对集合对象设置不可变. ...
- JavaScript大杂烩0 - WEB基础知识
1. 协议小结:HTTP协议与TCP/IP协议 现代Web应用开发的基础是HTTP协议,那么HTTP协议与我们熟知的TCP/IP协议有什么关系呢? 这个要从网络通信模型说起,简单的说,计算机通信就像两 ...
- pip更新及Requirement already up-to-date解决方法
pip更新及Requirement already up-to-date解决方法 文:铁乐与猫 2018-9-11 更新命令 将pip更新到最新版本 python -m pip install --u ...
- 4.7 Sublime Text3 中配置 Python环境 --之上安装Sublime 3
返回总目录 目录: 1.展示效果: 2.缺优分析: 3.下载Sublime Text3 (一)展示效果: 1.能够交互式编写Python代码: 2.可以编写文件式Python代码: 3.能够自动补齐代 ...
- python基础 - 控制语句
判断-if mood = True if mood: print('mood ok'); else: print('mood not OK') if-elif-else if a == 1: pass ...
- if语句(初学者)
用if语句可以构成分支结构.它根据给定的条件进行判断,以决定执行某个分支程序段.C语言的if语句有三种基本形式. 1.基本形式:if(表达式)语句 其语义是:如果表达式的值为真,则执行其后的语句,否则 ...
- mac系统如何在当前目录下打开终端
给大家推荐一个好用的终端工具 Go2Shell:https://itunes.apple.com/cn/app/go2shell/id445770608?mt=12 在没有这个工具之前 找了好多在当前 ...
- python五十七课——正则表达式(元字符)
1).匹配单个字符(数字.英文.其它) 符号位: []:表示一个字符位 [0123456789]:表示一位,取值范围:[0,9]之间的任何一个值 [0-9]:表示一位,取值范围:[0,9]之间的任何一 ...
- Graphviz安装及简单使用
Graphviz Windows环境安装: 1.官网下载 官网下载地址 2.配置环境变量 将graphviz安装目录下的bin文件夹添加到Path环境变量中: 3.验证是否安装并配置成功 进入wind ...