1. 程式人生 > >【模板】三維凸包

【模板】三維凸包

() space can problem oss https clear main tor

題目地址

【三維凸包】

這個是我照著lrj的藍書打的。

代碼

#include <bits/stdc++.h>
#define pb push_back
#define db double 
#define N 2005
#define eps 1e-9
using namespace std;
bool vis[N][N];
db ans = 0;
db rand01() {return rand()/(db)RAND_MAX;}
db randeps() {return (rand01() - 0.5) * eps;}
struct Point3 {
    db x, y, z;
    Point3(db x = 0, db y = 0, db z = 0): x(x), y(y), z(z){}
}P[N];
typedef Point3 Vector3;
Vector3 operator +(Vector3 A, Vector3 B) {
    return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
}
Vector3 operator -(Vector3 A, Vector3 B) {
    return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
}
Vector3 operator *(Vector3 A, db p) {
    return Vector3(A.x * p, A.y * p, A.z * p);
}
Vector3 operator /(Vector3 A, db p) {
    return Vector3(A.x / p, A.y / p, A.z / p);
}
Vector3 Cross(Vector3 A, Vector3 B) {
    return Vector3(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);
}
db Dot(Vector3 A, Vector3 B) {return A.x * B.x + A.y * B.y + A.z * B.z;}
db Length(Vector3 A) {return sqrt(Dot(A, A));}
struct Face {
    int v[3];
    Vector3 normal(Point3 *P) const{
        return Cross(P[v[1]] - P[v[0]], P[v[2]] - P[v[0]]);
    }
    int cansee(Point3 *P, int i) const {
        return Dot(P[i] - P[v[0]], normal(P)) > 0 ? 1 : 0;
    }
};
vector<Face> Ans;
vector<Face> CH3D(Point3 *P, int n) {
    vector<Face> cur;
    cur.clear();
    cur.pb((Face){0, 1, 2}); 
    cur.pb((Face){2, 1, 0});
    for (int i = 3; i < n; i ++) {
        vector<Face> nxt;
        for (int j = 0; j < (int)cur.size(); j ++) {
            Face& f = cur[j];
            int res = f.cansee(P, i);
            if (!res) nxt.pb(f);
            for (int k = 0; k < 3; k ++) vis[f.v[k]][f.v[(k + 1) % 3]]= res;
        }
        for (int j = 0; j < (int)cur.size(); j ++) {
            for (int k = 0; k < 3; k ++) {
                int a = cur[j].v[k], b = cur[j].v[(k + 1) % 3];
                if (vis[a][b] != vis[b][a] && vis[a][b]) nxt.pb((Face){a, b, i});
            }
        }
        cur = nxt;
    }
    return cur;
}
int n;
int main() {
    srand(19260817);
    scanf("%d", &n);
    for (int i = 0; i < n; i ++) scanf("%lf%lf%lf", &P[i].x, &P[i].y, &P[i].z);
    Ans = CH3D(P, n);
    for (int i = 0; i < (int)Ans.size(); i ++) ans += Length(Ans[i].normal(P)) / 2;
    printf("%.3lf\n", ans);
    return 0;
}

【模板】三維凸包