poj 3528 Ultimate Weapon (3D Convex Hull)
一道三维凸包的题目,题目要求求出三维凸包的表面积。看懂了网上的三维凸包的代码以后,自己写的代码,跟网上的模板有所不同。调了一个晚上,结果发现错的只是数组开太小。_(:з」∠)_
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath> using namespace std; const double EPS = 1e-;
const int N = ;
inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
struct Point {
double x, y, z;
Point() {}
Point(double x, double y, double z) : x(x), y(y), z(z) {}
bool operator < (Point a) const {
if (sgn(x - a.x)) return x < a.x;
if (sgn(y - a.y)) return y < a.y;
return z < a.z;
}
bool operator == (Point a) const { return !sgn(x - a.x) && !sgn(y - a.y) && !sgn(z - a.z);}
Point operator + (Point a) { return Point(x + a.x, y + a.y, z + a.z);}
Point operator - (Point a) { return Point(x - a.x, y - a.y, z - a.z);}
Point operator * (double p) { return Point(x * p, y * p, z * p);}
Point operator / (double p) { return Point(x / p, y / p, z / p);}
} ;
inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y + a.z * b.z;}
inline double dot(Point o, Point a, Point b) { return dot(a - o, b - o);}
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);}
inline Point cross(Point o, Point a, Point b) { return cross(a - o, b - o);}
inline double veclen(Point x) { return sqrt(dot(x, x));}
inline double area(Point o, Point a, Point b) { return veclen(cross(a - o, b - o)) / 2.0;}
// directed volume
inline double volume(Point o, Point a, Point b, Point c) { return dot(cross(a - o, b - o), c - o);} struct _3DCH {
Point pt[N];
int pcnt;
struct Face { // follow right-hand
int a, b, c;
bool ok;
Face() {}
Face(int a, int b, int c) : a(a), b(b), c(c) { ok = true;}
} ;
Face f[N << ];
int fcnt, fid[N][N];
bool outside(int p, int a, int b, int c) {
int dir = sgn(volume(pt[a], pt[b], pt[c], pt[p]));
return dir < ;
}
bool outside(int p, int x) { return outside(p, f[x].a, f[x].b, f[x].c);}
void addface(int p, int a, int b, int c) {
int dir = sgn(volume(pt[a], pt[b], pt[c], pt[p]));
if (dir == ) return ;
if (dir > ) {
f[fcnt] = Face(a, b, c);
fid[a][b] = fid[b][c] = fid[c][a] = fcnt++;
} else {
f[fcnt] = Face(c, b, a);
fid[c][b] = fid[b][a] = fid[a][c] = fcnt++;
}
}
bool dfs(int p, int x) {
if (!f[x].ok) return true;
if (outside(p, x)) {
f[x].ok = false;
if (!dfs(p, fid[f[x].b][f[x].a])) addface(f[x].c, f[x].b, f[x].a, p);
if (!dfs(p, fid[f[x].c][f[x].b])) addface(f[x].a, f[x].c, f[x].b, p);
if (!dfs(p, fid[f[x].a][f[x].c])) addface(f[x].b, f[x].a, f[x].c, p);
return true;
}
return false;
}
bool build() {
bool ok;
fcnt = ;
sort(pt, pt + pcnt);
pcnt = unique(pt, pt + pcnt) - pt;
ok = false;
for (int i = ; i < pcnt; i++) {
if (sgn(veclen(cross(pt[i], pt[], pt[])))) {
swap(pt[], pt[i]);
ok = true;
break;
}
}
if (!ok) return false;
ok = false;
for (int i = ; i < pcnt; i++) {
if (sgn(volume(pt[i], pt[], pt[], pt[]))) {
swap(pt[], pt[i]);
ok = true;
break;
}
}
if (!ok) return false;
addface(, , , );
addface(, , , );
addface(, , , );
addface(, , , );
for (int i = ; i < pcnt; i++) {
for (int j = fcnt - ; j >= ; j--) {
if (f[j].ok && outside(i, j)) {
dfs(i, j);
break;
}
}
}
int sz = fcnt;
fcnt = ;
for (int i = ; i < sz; i++) if (f[i].ok) f[fcnt++] = f[i];
return true;
}
double vol() {
Point O = Point(0.0, 0.0, 0.0);
double ret = 0.0;
for (int i = ; i < fcnt; i++) ret += volume(O, pt[f[i].a], pt[f[i].b], pt[f[i].c]);
return fabs(ret) / 6.0;
}
double facearea() {
double ret = 0.0;
for (int i = ; i < fcnt; i++) ret += area(pt[f[i].a], pt[f[i].b], pt[f[i].c]);
return ret;
}
} ch; int main() {
// freopen("in", "r", stdin);
while (cin >> ch.pcnt) {
for (int i = ; i < ch.pcnt; i++) scanf("%lf%lf%lf", &ch.pt[i].x, &ch.pt[i].y, &ch.pt[i].z);
ch.build();
printf("%.3f\n", ch.facearea());
= }
return ;
}
——written by Lyon
poj 3528 Ultimate Weapon (3D Convex Hull)的更多相关文章
- 【HDU 3662】3D Convex Hull
http://acm.hdu.edu.cn/showproblem.php?pid=3662 求给定空间中的点的三维凸包上有多少个面. 用增量法,不断加入点,把新加的点能看到的面都删掉,不能看到的面与 ...
- hdu 3662 3D Convex Hull
Problem - 3662 题意很简单,构造三维凸包,求凸包有多少个面. 代码如下: #include <cstdio> #include <iostream> #inclu ...
- 2D Convex Hulls and Extreme Points( Convex Hull Algorithms) CGAL 4.13 -User Manual
1 Introduction A subset S⊆R2 is convex if for any two points p and q in the set the line segment wit ...
- Monotone Chain Convex Hull(单调链凸包)
Monotone Chain Convex Hull(单调链凸包)算法伪代码: //输入:一个在平面上的点集P //点集 P 按 先x后y 的递增排序 //m 表示共a[i=0...m]个点,ans为 ...
- 凸包(Convex Hull)构造算法——Graham扫描法
凸包(Convex Hull) 在图形学中,凸包是一个非常重要的概念.简明的说,在平面中给出N个点,找出一个由其中某些点作为顶点组成的凸多边形,恰好能围住所有的N个点. 这十分像是在一块木板上钉了N个 ...
- Convex Hull 实现理论+自制Python代码
Convex Hull 概述 计算n维欧式空间散点集的凸包,有很多的方法.但是如果要实现快速运算则其难点在于:如何快速判断散点集的成员是否是在凸集的内部.如果可以简化判断的运算过程,则可以极大简化迭代 ...
- OpenCV入门之寻找图像的凸包(convex hull)
介绍 凸包(Convex Hull)是一个计算几何(图形学)中的概念,它的严格的数学定义为:在一个向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包. 在图像处理过程中,我们 ...
- convex hull
1 什么是convex hull 就是凸包,是计算几何中的一个概念,计算几何是计算机图形学的基础之一. 对于二维平面来说是这样的:对于二维平面上的点集,凸包是位于最外层的点构成的包围其它所有的点的凸多 ...
- opencv::凸包-Convex Hull
概念介绍 什么是凸包(Convex Hull),在一个多变形边缘或者内部任意两个点的连线都包含在多边形边界或者内部. 正式定义:包含点集合S中所有点的最小凸多边形称为凸包 Graham扫描算法 首先选 ...
随机推荐
- centos部分网站无法访问问题的解决
CentOS 5内核对TCP的读缓冲区大小有缺省设置,缺省为:net.ipv4.tcp_rmem = 4096 87380 4194304 解决办法就是将最后一个数字改小一点,具体操作就是在文件/et ...
- [翻译] MaxMind DB 文件格式规范
MaxMind DB 文件格式规范来源:http://maxmind.github.io/MaxMind-DB/翻译:御风(TX:965551582)2017-03-23 -------------- ...
- Phpstrom学习笔记
1.用*标识编辑过的文件 File - Editor – General - Editor Tabs 选中Mark modifyied tabs with asterisk
- JS---案例:手风琴 (利用封装好的动画函数)
案例:手风琴 封装好的动画函数在common.js里面 //function getStyle(element, attr) {...} //function animate( ...
- 顶级测试框架Jest指南:跑通一个完美的程序,就是教出一群像样的学生
facebook三大项目:yarn jest metro,有横扫宇宙之势. 而jest项目的宗旨为:减少测试一个项目所花费的时间成本和认知成本. --其实,它在让你当一个好老师. jest文档非常简略 ...
- 第一周<单元一聚类>
K-means 聚类算法 初始随机选择 而后不断更新 kmeans 应用 省份归类 调用kmeans方法所需要的参数 n_clusters 指定的聚类中心 init 初始聚类中心的初始化方法 默认k- ...
- 移动端fixed定位在底部,出现键盘后消失
jq var h=$(window).height(); $(window).resize(function() { if($(window).height()<h){ $('.nav').hi ...
- 【怪物】KMP畸形变种——扩展KMP
问题 参考51nod1304这道题: 很显然我们要求的是S的每个后缀与S的最长公共前缀的长度之和. 暴力 假设我们把next[i]表示为第i个后缀与S的最长公共前缀的长度. 现在我们想了:这个next ...
- Linux的一些简单命令操作总结
防火墙 查看防火墙状态 systemctl status iptables (或service iptables status) 关闭防火墙 systemctl stop iptables(或serv ...
- hdu4267 线段树
开始敲了一发线段树,觉得可以暴力一点的过,tle了.后来进行修改,发现了问题. 后来一看大神的做法,由于1<=k<=10,所以对于不同的k,有55个余,找答案的时候只要找不同的k值满足条件 ...