0%

80. Convex Checker

题目大意

思路讲解

image

原先的凸性检测没法检测出这样子的五角星。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 不允许自交的多边形,顺序都可以,会把 poly 变为 CCW 顺序(逆时针)
// AC https://qoj.ac/submission/2002121
bool isConvex(vector<Point> &poly) {
ll n = poly.size();
Point p1 = poly[1] - poly[0], p2 = poly[2] - poly[0];
if (sgn(cross(p1, p2)) <= 0) {
reverse(poly.begin(), poly.end());
}
// 找到字典序最小的点
ll pos_mn = 0;
for (int i = 1; i < n; ++i) {
if (poly[i] < poly[pos_mn]) {
pos_mn = i;
}
}
// Performs a left rotation on a range of elements
// 向左循环移动,把 pos_mn 移动到第一个 [0]
rotate(poly.begin(), poly.begin() + pos_mn, poly.end());
// 在一个标准的凸多边形中,如果我们站在最左下角的点(poly[0])往外看
// 其他所有顶点 poly[1], poly[2], ..., poly[n-1] 应该按照逆时针方向整齐排列。
// 从而排除星形(自交)多边形和乱序点集。
for (int i = 1; i < n - 1; ++i) {
if (sgn(cross(poly[i] - poly[0], poly[i + 1] - poly[0])) <= 0) {
return false;
}
}
// 判断单个内角是否 ≥ 180。
for (int i = 0; i < n; ++i) {
ll i1 = (i + 1) % n, i2 = (i + 2) % n;
Vector a = poly[i1] - poly[i], b = poly[i2] - poly[i1];
// 加上大于等于,就相当于排除所有的退化情况,不允许内角为 180 度
if (sgn(cross(a, b)) <= 0) {
return false;
}
}
return true;
}

AC代码

AC
https://qoj.ac/submission/2002045

AC https://qoj.ac/submission/2002100

AC https://qoj.ac/submission/2002121

心路历程(WA,TLE,MLE……)