bzoj 4445 小凸想跑步 - 半平面交
假设点的位置是$(x, y)$,那么可以用叉积来计算三角形的面积。
这样可以列出$n - 1$个不等式。
将每个化成形如$ax + by + c \leqslant 0$的形式。
然后分类讨论($b = 0的时候需要特殊处理$)将它转换成二维平面上的半平面。
接着做半平面交,算面积就好了。
Code
/**
* bzoj
* Problem#4445
* Accepted
* Time: 288ms
* Memory: 20068k
*/
#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
typedef bool boolean; const double eps = 1e-;
#define check(_s) cerr << _s << endl; inline int dcmp(double x) {
if (fabs(x) <= eps) return ;
return (x < ) ? (-) : ();
} typedef class Vector {
public:
double x, y; Vector(double x = 0.0, double y = 0.0):x(x), y(y) { }
}Point, Vector; ostream& operator << (ostream& os, Point a) {
os << "(" << a.x << ", " << a.y << ")";
return os;
} Vector operator + (Vector a, Vector b) {
return Vector(a.x + b.x, a.y + b.y);
} Vector operator - (Vector a, Vector b) {
return Vector(a.x - b.x, a.y - b.y);
} Vector operator * (double x, Vector a) {
return Vector(a.x * x, a.y * x);
} double cross(Vector a, Vector b) {
return a.x * b.y - a.y * b.x;
} double dot(Vector a, Vector b) {
return a.x * b.x + a.y * b.y;
} Point getLineIntersection(Point A, Vector v, Point B, Vector u) {
double t = (cross(B - A, u) / cross(v, u));
return A + t * v;
} typedef class Line {
public:
Point p;
Vector v;
double ang; Line() { }
Line(Point p, Vector v):p(p), v(v) {
ang = atan2(v.y, v.x);
} boolean operator < (Line b) const {
// return dcmp(cross(v, b.v)) > 0;
return ang < b.ang;
}
}Line; const int N = 1e5 + ; int n;
int st = , ed = , top;
Line *ls, *qs;
Point *ps; inline void init() {
scanf("%d", &n);
ps = new Point[(n << ) + ];
for (int i = ; i < n; i++)
scanf("%lf%lf", &ps[i].x, &ps[i].y);
} inline void build() {
int d;
Point cur, nxt, vec;
ls = new Line[(n << ) + ];
vec = ps[] - ps[];
ls[++top] = Line(ps[], vec);
double bx = vec.y, by = vec.x, bc = cross(vec, ps[]), nx, ny, nc;
for (int i = ; i < n; i++) {
cur = ps[i], nxt = ps[(i + ) % n], vec = nxt - cur;
nx = bx - vec.y, ny = by - vec.x, nc = bc - cross(vec, cur);
d = dcmp(ny);
if (!d) {
d = dcmp(nx);
if (!d) continue;
ls[++top] = Line(Point(-nc / nx, ), Vector(, -d)); } else {
nx /= ny, nc /= ny;
ls[++top] = Line(Point(, nc), Vector(-d, -nx * d));
}
ls[++top] = Line(cur, vec);
}
} boolean isCrossingOut(Line b, Line cur, Line a) {
assert (dcmp(cross(cur.v, a.v)));
// if (!dcmp(cross(cur.v, a.v))) return true;
Point p = getLineIntersection(cur.p, cur.v, a.p, a.v);
return dcmp(cross(p - b.p, b.v)) > ;
} inline void HalfPlaneIntersection(int n) {
sort(ls + , ls + n + );
qs = new Line[n + ];
for (int i = ; i <= n; i++) {
while (st < ed && isCrossingOut(ls[i], qs[ed], qs[ed - ])) ed--;
while (st < ed && isCrossingOut(ls[i], qs[st], qs[st + ])) st++;
qs[++ed] = ls[i];
if (st < ed && !dcmp(cross(qs[ed].v, qs[ed - ].v))) {
ed--;
if (dcmp(cross(qs[ed].p - ls[i].v, ls[i].v)) < )
qs[ed] = ls[i];
}
}
while (st < ed && isCrossingOut(qs[st], qs[ed], qs[ed - ])) ed--;
} inline double PolygonArea(Point *ps, int n) {
double rt = cross(ps[n], ps[]);
for (int i = ; i < n; i++)
rt += cross(ps[i], ps[i + ]);
return fabs(rt) / ;
} inline void solve() {
double all = PolygonArea(ps - , n);
build();
HalfPlaneIntersection(top);
// assert(st < ed - 1);
if (st >= ed - ) {
puts("0.0000");
return;
}
for (int i = st; i < ed; i++)
ps[i] = getLineIntersection(qs[i].p, qs[i].v, qs[i + ].p, qs[i + ].v);
ps[ed] = getLineIntersection(qs[ed].p, qs[ed].v, qs[st].p, qs[st].v);
printf("%.4f", PolygonArea(ps + (st - ), ed - st + ) / all);
} int main() {
init();
solve();
return ;
}
bzoj 4445 小凸想跑步 - 半平面交的更多相关文章
- 【BZOJ4445】[Scoi2015]小凸想跑步 半平面交
[BZOJ4445][Scoi2015]小凸想跑步 Description 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸n边形,N个顶点按照逆时针从0-n-l编号.现 ...
- 4445: [Scoi2015]小凸想跑步 半平面交
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4445 题解: 设点坐标,利用叉积可以解出当p坐标为\((x_p,y_p)\)时,与边i- ...
- 【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」小凸想跑步 解题报告
「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...
- Loj 2008 小凸想跑步
Loj 2008 小凸想跑步 \(S(P,p_0,p_1)<S(P,p_i,p_{i+1})\) 这个约束条件对于 \(P_x,P_y\) 是线性的,即将面积用向量叉积表示,暴力拆开,可得到 \ ...
- loj #2008. 「SCOI2015」小凸想跑步
#2008. 「SCOI2015」小凸想跑步 题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n nn 边形,N NN 个顶点按照逆时针从 0∼n−1 0 ...
- BZOJ 4445 [Scoi2015]小凸想跑步:半平面交
传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...
- 【bzoj4445 scoi2015】小凸想跑步
题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 nn 边形, nn 个顶点按照逆时针从 00 ∼ n - 1n−1 编号.现在小凸随机站在操场中的某个位置,标 ...
- [SCOI2015]小凸想跑步
题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n 边形, nn 个顶点按照逆时针从 0 ∼n−1 编号.现在小凸随机站在操场中的某个位置,标记为p点.将 p ...
随机推荐
- cocos2d-x 暂停/恢复 与场景相关(SceneGraph类型)的监听器
开发过程中,我们经常会遇到这样的情况:想要让一个Layer中所有的Node对象的事件都停止响应. 在响应用户事件后,又要恢复该Layer的所有事件响应. 如: 用户想要显示一个模式对话框,显示对话框后 ...
- 响应式布局css样式
核心css /*图片列表样式*/ .img-list{ margin:-15px 0 0 -15px; *display:inline-block; } /*响应式布局*/ @media screen ...
- Mybatis中的常用的三个查询方法
selectList 用于查询多条数据的情况,返回值是一个list集合.如果没有查到任何数据,返回没有元素的集合(空集合,不是null) selectOne 用于查询单条数据的情况,返回值是一个对象, ...
- composer----------composer基本命令和遇到一些问题解决方案
1.composer跟xdebug有冲突,每次用composer命令的时候都要报xdebug的错误,去php的配置文件里面将xdebug注释掉就可以了,但是我注释掉了以后还是不行.找了半天才看到,我用 ...
- React项目中使用Mobx状态管理(二)
并上一节使用的是普通的数据状态管理,不过官方推荐使用装饰器模式,而在默认的react项目中是不支持装饰器的,需要手动启用. 官方参考 一.添加配置 官方提供了四种方法, 方法一.使用TypeScrip ...
- 000-js判断电脑或手机登录
<script type="text/javascript"> try{ if(/Android|webOS|iPhone|iPod|BlackBerry/i.test ...
- JavaScript-switch-case-电话系统
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- pip install pyinstaller
C:\Users\coder211\Desktop>pip install pyinstallerCollecting pyinstaller Downloading PyInstaller-3 ...
- EasyUI创建DataGrid及冻结列的两种方式
第一种方式:通过HTML标签创建数据表格控件 <table class="easyui-datagrid" title="基本数据表格" style ...
- mysql 问题:wait_timeout
1,show global variables like 'wait_timeout'; 查询'wait_timeout' 默认是8天即28800秒 2,修改 windows 安装目录下的my.ini ...