hdu 3662 3D Convex Hull (三维凸包 模板1)

来源:互联网 发布:js给input value赋值 编辑:程序博客网 时间:2024/05/17 23:09


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3662

题目意思:给出n 个三维的点,求这些点组成的凸包的面数


//============================================================================// Name        : hdu3662.cpp// Author      : ssslpk// Version     :// Copyright   : Your copyright notice// Description : Hello World in C++, Ansi-style//============================================================================#include <iostream>#include <stdio.h>#include <stdlib.h>#include <cmath>using namespace std;#define X 0#define Y 1#define Z 2#define eps 1e-8#define zero(x) (((x)>0?(x):-(x))<eps)typedef struct Vertex *tVertex;typedef struct Edge *tEdge;typedef struct Face *tFace;struct point3{double x,y,z;};struct Vertex {    double v[3];    int vnum;    bool onhull, processed;    tEdge duplicate;        /* pointer to incident cone edge (or NULL) */    tVertex next, prev;};struct Edge {    tFace adjface[2];    tVertex endpts[2];    tFace newface;            /* pointer to incident cone face. */    bool remove;            /* T iff edge should be remove. */    tEdge next, prev;};struct Face {    tEdge edge[3];    tVertex vertex[3];    bool visible;            /* T iff face visible from new point. */    tFace next, prev;};tVertex vertices = NULL;tEdge edges     = NULL;tFace faces     = NULL;#define ADD(head, p) if (head) {\    p->next = head;\    p->prev = head->prev;\    head->prev = p;\    p->prev->next = p;\}\else {\    head = p;\    head->next = head->prev = p;\}#define DELETE(head, p) if (head) {\    if (head == head->next)\    head = NULL;\    else if (p == head)\    head = head->next;\    p->next->prev = p->prev;\    p->prev->next = p->next;\    delete (p);\}const double EPS = 1e-10;int sgn(double d) {    return d < -EPS ? -1 : d > EPS;}//ŒÆËãcross product U x Vpoint3 xmult(point3 u,point3 v){    point3 ret;    ret.x=u.y*v.z-v.y*u.z;    ret.y=u.z*v.x-u.x*v.z;    ret.z=u.x*v.y-u.y*v.x;    return ret;}//ŒÆËãdot product U . Vdouble dmult(point3 u,point3 v){    return u.x*v.x+u.y*v.y+u.z*v.z;}//ÊžÁ¿²î U - Vpoint3 subt(point3 u,point3 v){    point3 ret;    ret.x=u.x-v.x;    ret.y=u.y-v.y;    ret.z=u.z-v.z;    return ret;}//È¡ÆœÃæ·šÏòÁ¿point3 pvec(point3 s1,point3 s2,point3 s3){    return xmult(subt(s1,s2),subt(s2,s3));}//ÏòÁ¿ŽóСdouble vlen(point3 p){    return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);}tVertex    MakeNullVertex(void) {    tVertex v = new Vertex;    v->duplicate = NULL;    v->onhull = false;    v->processed = false;    ADD(vertices, v);    return v;}tEdge MakeNullEdge(void) {    tEdge e = new Edge;    e->adjface[0] = e->adjface[1] = e->newface = NULL;    e->endpts[0] = e->endpts[1] = NULL;    e->remove = false;    ADD(edges, e);    return e;}tFace MakeNullFace(void) {    tFace f = new Face;    for (int i = 0; i < 3; ++i) {        f->edge[i] = NULL;        f->vertex[i] = NULL;    }    f->visible = false;    ADD(faces, f);    return f;}tFace MakeFace(tVertex v0, tVertex v1, tVertex v2, tFace fold) {    tEdge e0, e1, e2;    if (!fold) {        e0 = MakeNullEdge();        e1 = MakeNullEdge();        e2 = MakeNullEdge();    }    else {        e0 = fold->edge[2];        e1 = fold->edge[1];        e2 = fold->edge[0];    }    e0->endpts[0] = v0; e0->endpts[1] = v1;    e1->endpts[0] = v1; e1->endpts[1] = v2;    e2->endpts[0] = v2; e2->endpts[1] = v0;    tFace f = MakeNullFace();    f->edge[0] = e0; f->edge[1] = e1; f->edge[2] = e2;    f->vertex[0] = v0; f->vertex[1] = v1; f->vertex[2] = v2;    e0->adjface[0] = e1->adjface[0] = e2->adjface[0] = f;    return f;}void CleanEdges(void) {    tEdge e = edges;    do {        if (e->newface) {            if (e->adjface[0]->visible)                e->adjface[0] = e->newface;            else e->adjface[1] = e->newface;            e->newface = NULL;        }        e = e->next;    } while (e != edges);    while (edges && edges->remove) {        e = edges;        DELETE(edges, e);    }    e = edges->next;    do {        if (e->remove) {            tEdge t = e;            e = e->next;            DELETE(edges, t);        }        else e = e->next;    } while (e != edges);}void CleanFaces(void) {    tFace f;    while (faces && faces->visible) {        f = faces;        DELETE(faces, f);    }    f = faces->next;    do {        if (f->visible) {            tFace t = f;            f = f->next;            DELETE(faces, t);        }        else f = f->next;    } while (f != faces);}void CleanVertices(tVertex *pvnext) {    tVertex v, t;    tEdge e = edges;    do {        e->endpts[0]->onhull = e->endpts[1]->onhull = true;        e = e->next;    } while (e != edges);    while (vertices && vertices->processed && !vertices->onhull) {        if (v == *pvnext)            *pvnext = v->next;        v = vertices;        DELETE(vertices, v);    }    v = vertices->next;    do {        if (v->processed && !v->onhull) {            t = v;            v = v->next;            DELETE(vertices, t)        }        else v = v->next;    } while (v != vertices);    v = vertices;    do {        v->duplicate = NULL;        v->onhull = false;        v = v->next;    } while (v != vertices);}void CleanUp(tVertex *pvnext) {    CleanEdges();    CleanFaces();    CleanVertices(pvnext);}void SubVec(double a[3], double b[3], double c[3]) {    for (int i = 0; i < 2; ++i) c[i] = a[i] - b[i];}bool Collinear(tVertex a, tVertex b, tVertex c) {    double c0 = (c->v[Z] - a->v[Z]) * (b->v[Y] - a->v[Y]) - (b->v[Z] - a->v[Z]) * (c->v[Y] - a->v[Y]);    double c1 = (b->v[Z] - a->v[Z]) * (c->v[X] - a->v[X]) - (b->v[X] - a->v[X]) * (c->v[Z] - a->v[Z]);    double c2 = (b->v[X] - a->v[X]) * (c->v[Y] - a->v[Y]) - (b->v[Y] - a->v[Y]) * (c->v[X] - a->v[X]);    return c0 == 0 && c1 == 0 && c2 == 0;}double  Volume(tFace f, tVertex p) {    double  ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz;    ax = f->vertex[0]->v[X] - p->v[X];    ay = f->vertex[0]->v[Y] - p->v[Y];    az = f->vertex[0]->v[Z] - p->v[Z];    bx = f->vertex[1]->v[X] - p->v[X];    by = f->vertex[1]->v[Y] - p->v[Y];    bz = f->vertex[1]->v[Z] - p->v[Z];    cx = f->vertex[2]->v[X] - p->v[X];    cy = f->vertex[2]->v[Y] - p->v[Y];    cz = f->vertex[2]->v[Z] - p->v[Z];    double vol = (ax * (by * cz - bz * cy) + ay * (bz * cx - bx * cz) + az * (bx * cy - by * cx));    return vol;}void DoubleTriangle(void) {    tVertex  v0, v1, v2, v3, t;    tFace f0, f1 = NULL;    tEdge e0, e1, e2, s;    v0 = vertices;    while (Collinear(v0, v0->next, v0->next->next))        if ((v0 = v0->next) == vertices)            printf("DoubleTriangle:  All points are Collinear!\n"), exit(0);    v1 = v0->next;    v2 = v1->next;    v0->processed = true;    v1->processed = true;    v2->processed = true;    f0 = MakeFace(v0, v1, v2, f1);    f1 = MakeFace(v2, v1, v0, f0);    f0->edge[0]->adjface[1] = f1;    f0->edge[1]->adjface[1] = f1;    f0->edge[2]->adjface[1] = f1;    f1->edge[0]->adjface[1] = f0;    f1->edge[1]->adjface[1] = f0;    f1->edge[2]->adjface[1] = f0;    v3 = v2->next;    int vol = sgn(Volume(f0, v3));    while (!vol) {        if ((v3 = v3->next) == v0)            printf("DoubleTriangle:  All points are coplanar!\n"), exit(0);        vol = sgn(Volume(f0, v3));    }    vertices = v3;}void MakeCcw(tFace f, tEdge e, tVertex p) {    tFace fv;    if (e->adjface[0]->visible) fv = e->adjface[0];    else fv = e->adjface[1];    int i;    for (i = 0; fv->vertex[i] != e->endpts[0]; ++i)        ;    if (fv->vertex[(i + 1) % 3] != e->endpts[1]) {        f->vertex[0] = e->endpts[1];        f->vertex[1] = e->endpts[0];    }    else {        f->vertex[0] = e->endpts[0];        f->vertex[1] = e->endpts[1];        swap(f->edge[1], f->edge[2]);    }    f->vertex[2] = p;}tFace MakeConeFace(tEdge e, tVertex p) {    tEdge new_edge[2];    for (int i = 0; i < 2; ++i)        if (!(new_edge[i] = e->endpts[i]->duplicate)) {            new_edge[i] = MakeNullEdge();            new_edge[i]->endpts[0] = e->endpts[i];            new_edge[i]->endpts[1] = p;            e->endpts[i]->duplicate = new_edge[i];        }    tFace new_face = MakeNullFace();    new_face->edge[0] = e;    new_face->edge[1] = new_edge[0];    new_face->edge[2] = new_edge[1];    MakeCcw(new_face, e, p);    for (int i = 0; i < 2; ++i)        for (int j = 0; j < 2; ++j)            if (!new_edge[i]->adjface[j]) {                new_edge[i]->adjface[j] = new_face;                break;            }    return new_face;}bool AddOne(tVertex p) {    bool visable = false;    tFace f = faces;    do {        int vol = sgn(Volume(f, p));        if (vol < 0) {            f->visible = true;            visable = true;        }        f = f->next;    } while (f != faces);    if (!visable) {        p->onhull = false;        return false;    }    tEdge e = edges;    do {        tEdge temp = e->next;        if (e->adjface[0]->visible && e->adjface[1]->visible)            e->remove = true;        else if (e->adjface[0]->visible || e->adjface[1]->visible)            e->newface = MakeConeFace(e, p);        e = temp;    } while (e != edges);    return true;}void ConstructHull(void) {    tVertex v = vertices;    tVertex vnext;    do {        vnext = v->next;        if (!v->processed) {            v->processed = true;            AddOne(v);            CleanUp(&vnext);        }        v = vnext;    } while (v != vertices);}double sqr(double x) {    return x * x;}double dist(Vertex a, Vertex b) {    return sqrt(sqr(a.v[X] - b.v[X]) + sqr(a.v[Y] - b.v[Y]) + sqr(a.v[Z] - b.v[Z]));}void Solve() {    DoubleTriangle();    ConstructHull();}int dots_onplane(point3 a,point3 b,point3 c,point3 d){    return zero(dmult(pvec(a,b,c),subt(d,a)));}int parallel(point3 u1,point3 u2,point3 u3,point3 v1,point3 v2,point3 v3){    return vlen(xmult(pvec(u1,u2,u3),pvec(v1,v2,v3)))<eps;}point3 vchangetop(Vertex p){    point3 v;    v.x = p.v[X]; v.y = p.v[Y]; v.z = p.v[Z];    return v;}void printout(point3 p){    printf("%lf %lf %lf\n",p.x,p.y,p.z);}int FaceArea(void) {    int ans = 0;    bool same;    tFace ff,f = faces;    do {        point3 p0 = vchangetop(*(f->vertex[0])), p1 = vchangetop(*(f->vertex[1])), p2 = vchangetop(*(f->vertex[2]));        ff = faces;        same = false;        while (ff!=f){            point3 v0 = vchangetop(*(ff->vertex[0])), v1 = vchangetop(*(ff->vertex[1])), v2 = vchangetop(*(ff->vertex[2]));            if (parallel(p0,p1,p2,v0,v1,v2) && dots_onplane(p0,p1,p2,v0)){                same = true;                break;            }            ff = ff->next;        }        if (!same) ans++;        f = f->next;    } while (f != faces);    return ans;}int main(void) {    double x, y, z;    int N;    while (scanf("%d", &N) != EOF) {        vertices = NULL;        edges     = NULL;        faces     = NULL;        for (int i = 0; i < N; ++i) {            scanf ("%lf %lf %lf", &x, &y, &z );            tVertex v = MakeNullVertex();            v->v[X] = x;            v->v[Y] = y;            v->v[Z] = z;            v->vnum = i;        }        if (N <= 3) printf("0\n");        else {            Solve();            printf("%d\n", FaceArea());        }    }    return 0;}


原创粉丝点击