二维凸包学习小记

初三都毕业了还不会计算几何,真TM蛋痛。

不过事实证明计算几何都是送命题,去死磕一不小心就翻车了,考场时还是要谨慎点。

二维凸包定义:

一个二维平面上有一些点,现在要求一个凸多边形,使它的顶点在这些点上,且这个凸多边形的内部(包括边上)包括了所有的点。

构建二维凸包:

首先找到一个一定在凸包上的点,那么找这些点中最下的点(如果y相同取x最小的)就行了。

然后极角排序(不用求出角,叉积判正负即可)。

接着单调栈,也是用叉积判正负即可。

注意精度误差。

裸题:
【SHTSC2012day1】信用卡凸包

Code:

#include<cmath>
#include<cstdio>
#include<algorithm>
#define db double
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define abs(a) ((a) > 0 ? (a) : -(a))
using namespace std;

const db pi = acos(-1), eps = 1e-8;
struct P {
    db x, y;
    P(db _x = 0, db _y = 0) {x = _x, y = _y;}
};
P operator +(P a, P b) {return P(a.x + b.x, a.y + b.y);}
P operator -(P a, P b) {return P(a.x - b.x, a.y - b.y);}
P operator *(P a, db b) {return P(a.x * b, a.y * b);}
db operator ^(P a, P b) {return a.x * b.y - a.y * b.x;}
P operator *(P a, P b) {return P(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
P angle(db x) {return P(cos(x), sin(x));}
P rotate(P a, db x) {return a * angle(x);}
db len(P a) {return sqrt(a.x * a.x + a.y * a.y);}
db dis(P a, P b) {return len(a - b);}

const int N = 1e5 + 5;

int n, m, z0, u, z[N]; db a, b, r, x, y, theta;
P d[N];

int cmp(P a, P b) {
    return ((a - d[1]) ^ (b - d[1])) + eps >= 0;
}
int main() {
    scanf("%d %lf %lf %lf", &n, &a, &b, &r);
    fo(i, 1, n) {
        scanf("%lf %lf %lf", &x, &y, &theta);
        d[++ m] = rotate(P(- b / 2 + r, - a / 2 + r), theta) + P(x, y);
        d[++ m] = rotate(P(b / 2 - r, - a / 2 + r), theta) + P(x, y);
        d[++ m] = rotate(P(- b / 2 + r, a / 2 - r), theta) + P(x, y);
        d[++ m] = rotate(P(b / 2 - r, a / 2 - r), theta) + P(x, y);
    }
    u = 1;
    fo(i, 2, m) if(d[i].y < d[u].y || (abs(d[i].y - d[u].y) <= eps && d[i].x - eps < d[u].x))
        u = i;
    swap(d[1], d[u]);
    sort(d + 2, d + m + 1, cmp);
    z[z0 = 1] = 1; z[z0 = 2] = 2;
    fo(i, 3, m) {
        while(z0 > 1 && ((d[i] - d[z[z0 - 1]]) ^ (d[z[z0]] - d[z[z0 - 1]])) + eps >= 0)
            z0 --;
        z[++ z0] = i;
    }
    db ans = 2 * r * pi;
    fo(i, 2, z0) ans += dis(d[z[i]], d[z[i - 1]]);
    ans += dis(d[z[1]], d[z[z0]]);
    printf("%.2lf", ans);
}

猜你喜欢

转载自blog.csdn.net/cold_chair/article/details/80992199