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 ...
随机推荐
- gitlab数据迁移至其他gitlb服务器上
需求: A : 待迁移服务器,上边存有数据 B:接收项目得服务器,本身存在数据 验证方案: 一,搭建gitlab8.15.2 OS:rhel7.4 yum install policycoreutil ...
- C++二进制字符串转Base64字符串 Base64字符串转二进制字符串
封装成类的 . base64格式的字符串,只包含大小写字母.零到九,以及 + / //___base_64.h /*base_64.h文件*/ #ifndef BASE_64_H #define BA ...
- VB脚本错误,系统找不到制定的文件 。代码:80070002
希望得到网友的答案:非常感谢!
- VMware vSphere
在进行操作vSphere产品之前,就曾经对它进行过一个简单了解:[运维]VMware vSphere简单了解,现在再回头看,发现了解的真的是太简单了.经过前一段时间学习之后,对它又有了新的感悟,再来谈 ...
- C# Control.Invoke匿名委托
if (txbValue.InvokeRequired) txbValue.Invoke(new MethodInvoker(delegate() { ...
- Unity shader学习之Alpha Test的阴影
Alpha Test的阴影, shader如下: // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClip ...
- linux基本格式和常用目录命令一
1: cd 绝对路径 2: cd 相对路径 名字开头 ./开头 ../开头 3: cd ~: 去到当前用户所在目录; 4: pwd获取当前的路径的绝对路径; 5: ls 与ls -l 6: cat 操 ...
- Spark学习之路 (六)Spark Transformation和Action
Transformation算子 基本的初始化 java static SparkConf conf = null; static JavaSparkContext sc = null; static ...
- [转载]ORA-01502错误成因和解决方法
检查一下索引状态,我们会注意到索引已经是“UNUSABLE”了.SQL> select index_name,index_type,tablespace_name,table_type,stat ...
- [转载]String.Empty、string=”” 和null的区别
String.Empty是string类的一个静态常量: String.Empty和string=””区别不大,因为String.Empty的内部实现是: 1 2 3 4 5 6 7 8 9 10 1 ...