poj 3528 Ultimate Weapon (3D Convex Hull)

3528 -- Ultimate Weapon

  一道三维凸包的题目,题目要求求出三维凸包的表面积。看懂了网上的三维凸包的代码以后,自己写的代码,跟网上的模板有所不同。调了一个晚上,结果发现错的只是数组开太小。_(:з」∠)_

代码如下:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 
  7 using namespace std;
  8 
  9 const double EPS = 1e-10;
 10 const int N = 555;
 11 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
 12 struct Point {
 13     double x, y, z;
 14     Point() {}
 15     Point(double x, double y, double z) : x(x), y(y), z(z) {}
 16     bool operator < (Point a) const {
 17         if (sgn(x - a.x)) return x < a.x;
 18         if (sgn(y - a.y)) return y < a.y;
 19         return z < a.z;
 20     }
 21     bool operator == (Point a) const { return !sgn(x - a.x) && !sgn(y - a.y) && !sgn(z - a.z);}
 22     Point operator + (Point a) { return Point(x + a.x, y + a.y, z + a.z);}
 23     Point operator - (Point a) { return Point(x - a.x, y - a.y, z - a.z);}
 24     Point operator * (double p) { return Point(x * p, y * p, z * p);}
 25     Point operator / (double p) { return Point(x / p, y / p, z / p);}
 26 } ;
 27 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y + a.z * b.z;}
 28 inline double dot(Point o, Point a, Point b) { return dot(a - o, b - o);}
 29 inline Point cross(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);}
 30 inline Point cross(Point o, Point a, Point b) { return cross(a - o, b - o);}
 31 inline double veclen(Point x) { return sqrt(dot(x, x));}
 32 inline double area(Point o, Point a, Point b) { return veclen(cross(a - o, b - o)) / 2.0;}
 33 // directed volume
 34 inline double volume(Point o, Point a, Point b, Point c) { return dot(cross(a - o, b - o), c - o);}
 35 
 36 struct _3DCH {
 37     Point pt[N];
 38     int pcnt;
 39     struct Face { // follow right-hand
 40         int a, b, c;
 41         bool ok;
 42         Face() {}
 43         Face(int a, int b, int c) : a(a), b(b), c(c) { ok = true;}
 44     } ;
 45     Face f[N << 3];
 46     int fcnt, fid[N][N];
 47     bool outside(int p, int a, int b, int c) {
 48         int dir = sgn(volume(pt[a], pt[b], pt[c], pt[p]));
 49         return dir < 0;
 50     }
 51     bool outside(int p, int x) { return outside(p, f[x].a, f[x].b, f[x].c);}
 52     void addface(int p, int a, int b, int c) {
 53         int dir = sgn(volume(pt[a], pt[b], pt[c], pt[p]));
 54         if (dir == 0) return ;
 55         if (dir > 0) {
 56             f[fcnt] = Face(a, b, c);
 57             fid[a][b] = fid[b][c] = fid[c][a] = fcnt++;
 58         } else {
 59             f[fcnt] = Face(c, b, a);
 60             fid[c][b] = fid[b][a] = fid[a][c] = fcnt++;
 61         }
 62     }
 63     bool dfs(int p, int x) {
 64         if (!f[x].ok) return true;
 65         if (outside(p, x)) {
 66             f[x].ok = false;
 67             if (!dfs(p, fid[f[x].b][f[x].a])) addface(f[x].c, f[x].b, f[x].a, p);
 68             if (!dfs(p, fid[f[x].c][f[x].b])) addface(f[x].a, f[x].c, f[x].b, p);
 69             if (!dfs(p, fid[f[x].a][f[x].c])) addface(f[x].b, f[x].a, f[x].c, p);
 70             return true;
 71         }
 72         return false;
 73     }
 74     bool build() {
 75         bool ok;
 76         fcnt = 0;
 77         sort(pt, pt + pcnt);
 78         pcnt = unique(pt, pt + pcnt) - pt;
 79         ok = false;
 80         for (int i = 2; i < pcnt; i++) {
 81             if (sgn(veclen(cross(pt[i], pt[0], pt[1])))) {
 82                 swap(pt[2], pt[i]);
 83                 ok = true;
 84                 break;
 85             }
 86         }
 87         if (!ok) return false;
 88         ok = false;
 89         for (int i = 3; i < pcnt; i++) {
 90             if (sgn(volume(pt[i], pt[0], pt[1], pt[2]))) {
 91                 swap(pt[3], pt[i]);
 92                 ok = true;
 93                 break;
 94             }
 95         }
 96         if (!ok) return false;
 97         addface(0, 1, 2, 3);
 98         addface(1, 2, 3, 0);
 99         addface(2, 3, 0, 1);
100         addface(3, 0, 1, 2);
101         for (int i = 4; i < pcnt; i++) {
102             for (int j = fcnt - 1; j >= 0; j--) {
103                 if (f[j].ok && outside(i, j)) {
104                     dfs(i, j);
105                     break;
106                 }
107             }
108         }
109         int sz = fcnt;
110         fcnt = 0;
111         for (int i = 0; i < sz; i++) if (f[i].ok) f[fcnt++] = f[i];
112         return true;
113     }
114     double vol() {
115         Point O = Point(0.0, 0.0, 0.0);
116         double ret = 0.0;
117         for (int i = 0; i < fcnt; i++) ret += volume(O, pt[f[i].a], pt[f[i].b], pt[f[i].c]);
118         return fabs(ret) / 6.0;
119     }
120     double facearea() {
121         double ret = 0.0;
122         for (int i = 0; i < fcnt; i++) ret += area(pt[f[i].a], pt[f[i].b], pt[f[i].c]);
123         return ret;
124     }
125 } ch;
126 
127 int main() {
128 //    freopen("in", "r", stdin);
129     while (cin >> ch.pcnt) {
130         for (int i = 0; i < ch.pcnt; i++) scanf("%lf%lf%lf", &ch.pt[i].x, &ch.pt[i].y, &ch.pt[i].z);
131         ch.build();
132         printf("%.3f
", ch.facearea());
133 =    }
134     return 0;
135 }
View Code

——written by Lyon