三维凸包

模板题:洛谷p4724

#include<bits/stdc++.h>
#define eps 1e-9;
using namespace std;
const int N=500010;
int n;
int vis[1010][1010];
struct Point{
    double x,y,z;
    void shake(){
        double Rand=(rand()/RAND_MAX-0.5)*eps;
        x+=Rand;y+=Rand;z+=Rand;
    }
    double len(){
        return sqrt(x*x+y*y+z*z);
    }
}point[N];
Point operator +(Point A,Point B){
    return (Point){A.x+B.x,A.y+B.y,A.z+B.z};
}
Point operator -(Point A,Point B){
    return (Point){A.x-B.x,A.y-B.y,A.z-B.z};
}
Point operator ^(Point A,Point B){
    return (Point){A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x};
}
double operator *(Point A,Point B){
    return A.x*B.x+A.y*B.y+A.z*B.z;
}
struct Plane{
    int num[3];
    Point legal(){
        Point A=point[num[1]]-point[num[0]];
        Point B=point[num[2]]-point[num[0]];
        return A^B; 
    }
    double S(){
        return legal().len()/2.0;
    }
}hull[N],stk[N];
int tp,cnt;
double len(Point A,Plane B){
    Point legal=B.legal();
    return legal*(A-point[B.num[0]])/legal.len();
}
bool see(Point A,Plane B){
    return B.legal()*(A-point[B.num[0]])>0.0;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].z);
        point[i].shake();
    }
    hull[++cnt]={1,2,3};
    hull[++cnt]={3,2,1};
    for(int i=4;i<=n;i++){
        for(int j=1;j<=cnt;j++){
            int v=see(point[i],hull[j]);
            if(!v)stk[++tp]=hull[j];
            for(int now=0;now<3;now++){
                int next=(now+1)%3;
                int from=hull[j].num[now];
                int to=hull[j].num[next];
                vis[from][to]=v;
            }
        }
        for(int j=1;j<=cnt;j++){
            for(int now=0;now<3;now++){
                int next=(now+1)%3;
                int from=hull[j].num[now];
                int to=hull[j].num[next];
                if(vis[from][to]&&!vis[to][from]){
                    stk[++tp]={from,to,i};
                }
            }
        }
        for(int j=1;j<=tp;j++){
            hull[j]=stk[j];
        }
        cnt=tp,tp=0;
    }
    double ans=0;
    for(int i=1;i<=cnt;i++){
        ans+=hull[i].S();
    }
    printf("%.3f\n",ans);
}
hull

 

posted @ 2020-02-06 17:00  passione  阅读(96)  评论(0编辑  收藏  举报