hdu 3662 3D Convex Hull

Problem - 3662

  题意很简单,构造三维凸包,求凸包有多少个面。

代码如下:

  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 = 333;
 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(o, a, b)) / 2.0;}
 33 inline double volume(Point o, Point a, Point b, Point c) { return dot(cross(o, a, b), c - o) / 6.0;}
 34 
 35 struct _3DCH{
 36     Point pt[N];
 37     int pcnt;
 38     struct Face {
 39         int a, b, c;
 40         bool ok;
 41         Face() {}
 42         Face(int a, int b, int c) : a(a), b(b), c(c) { ok = true;}
 43     } fc[N << 2];
 44     int fcnt;
 45     int fid[N][N];
 46 
 47     bool outside(int p, int a, int b, int c) { return sgn(volume(pt[a], pt[b], pt[c], pt[p])) < 0;}
 48     bool outside(int p, int f) { return outside(p, fc[f].a, fc[f].b, fc[f].c);}
 49     void addface(int a, int b, int c, int d) {
 50         if (outside(d, a, b, c)) fc[fcnt] = Face(c, b, a), fid[c][b] = fid[b][a] = fid[a][c] = fcnt++;
 51         else fc[fcnt] = Face(a, b, c), fid[a][b] = fid[b][c] = fid[c][a] = fcnt++;
 52     }
 53 
 54     bool dfs(int p, int f) {
 55         if (!fc[f].ok) return true;
 56         int a = fc[f].a, b = fc[f].b, c = fc[f].c;
 57         if (outside(p, a, b, c)) {
 58             fc[f].ok = false;
 59             if (!dfs(p, fid[b][a])) addface(p, a, b, c);
 60             if (!dfs(p, fid[c][b])) addface(p, b, c, a);
 61             if (!dfs(p, fid[a][c])) addface(p, c, a, b);
 62             return true;
 63         }
 64         return false;
 65     }
 66     void build() {
 67         bool ok;
 68         fcnt = 0;
 69         sort(pt, pt + pcnt);
 70         pcnt = unique(pt, pt + pcnt) - pt;
 71         ok = false;
 72         for (int i = 2; i < pcnt; i++) {
 73             if (sgn(area(pt[0], pt[1], pt[i]))) {
 74                 ok = true;
 75                 swap(pt[i], pt[2]);
 76                 break;
 77             }
 78         }
 79         if (!ok) return ;
 80         ok = false;
 81         for (int i = 3; i < pcnt; i++) {
 82             if (sgn(volume(pt[0], pt[1], pt[2], pt[i]))) {
 83                 ok = true;
 84                 swap(pt[i], pt[3]);
 85                 break;
 86             }
 87         }
 88         if (!ok) return ;
 89         addface(0, 1, 2, 3);
 90         addface(1, 2, 3, 0);
 91         addface(2, 3, 0, 1);
 92         addface(3, 0, 1, 2);
 93         for (int i = 4; i < pcnt; i++) {
 94             for (int j = fcnt - 1; j >= 0; j--) {
 95                 if (outside(i, j)) {
 96                     dfs(i, j);
 97                     break;
 98                 }
 99             }
100         }
101         int sz = fcnt;
102         fcnt = 0;
103         for (int i = 0; i < sz; i++) if (fc[i].ok) fc[fcnt++] = fc[i];
104     }
105     double facearea() {
106         double ret = 0.0;
107         for (int i = 0; i < fcnt; i++) ret += area(pt[fc[i].a], pt[fc[i].b], pt[fc[i].c]);
108         return ret;
109     }
110     bool same(int i, int j) {
111         int a = fc[i].a, b = fc[i].b, c = fc[i].c;
112         if (sgn(volume(pt[a], pt[b], pt[c], pt[fc[j].a]))) return false;
113         if (sgn(volume(pt[a], pt[b], pt[c], pt[fc[j].b]))) return false;
114         if (sgn(volume(pt[a], pt[b], pt[c], pt[fc[j].c]))) return false;
115         return true;
116     }
117     int facecnt() {
118         int cnt = 0;
119         for (int i = 0; i < fcnt; i++) {
120             bool ok = true;
121             for (int j = 0; j < i; j++) {
122                 if (same(i, j)) {
123                     ok = false;
124                     break;
125                 }
126             }
127             if (ok) cnt++;
128         }
129         return cnt;
130     }
131 } ch;
132 
133 int main() {
134 //    freopen("in", "r", stdin);
135     int n;
136     double x, y, z;
137     while (~scanf("%d", &ch.pcnt)) {
138         for (int i = 0; i < ch.pcnt; i++) {
139             scanf("%lf%lf%lf", &x, &y, &z);
140             ch.pt[i] = Point(x, y, z);
141         }
142         ch.build();
143 //        printf("%.3f\n", ch.facearea());
144         printf("%d\n", ch.facecnt());
145     }
146     return 0;
147 }
View Code

  三维凸包还是挺简单的,不用抄模板也能敲出来。不过,还不熟练,敲了接近一个钟。

 

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/p/hdu_3662_Lyon.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理,美食推荐管理,酒店推荐管理,周边推荐管理,分享圈管理,我的收藏管理,系统管理。用户可以在微信小程序上注册登录,进行每日签到,防疫查询,可以在分享圈里面进行分享自己想要分享的内容,查看和收藏景点以及美食的推荐等操作。因而具有一定的实用性。 本站后台采用Java的SSM框架进行后台管理开发,可以在浏览器上登录进行后台数据方面的管理,MySQL作为本地数据库,微信小程序用到了微信开发者工具,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得旅游社交小程序管理工作系统化、规范化。 管理员可以管理用户信息,可以对用户信息添加修改删除。管理员可以对景点推荐信息进行添加修改删除操作。管理员可以对分享圈信息进行添加,修改,删除操作。管理员可以对美食推荐信息进行添加,修改,删除操作。管理员可以对酒店推荐信息进行添加,修改,删除操作。管理员可以对周边推荐信息进行添加,修改,删除操作。 小程序用户是需要注册才可以进行登录的,登录后在首页可以查看相关信息,并且下面导航可以点击到其他功能模块。在小程序里点击我的,会出现关于我的界面,在这里可以修改个人信息,以及可以点击其他功能模块。用户想要把一些信息分享到分享圈的时候,可以点击新增,然后输入自己想要分享的信息就可以进行分享圈的操作。用户可以在景点推荐里面进行收藏和评论等操作。用户可以在美食推荐模块搜索和查看美食推荐的相关信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值