\(\color{#0066ff}{题目描述}\)

给出空间中n个点,求凸包表面积。

\(\color{#0066ff}{输入格式}\)

第一行一个整数n,表示点数。

接下来n行,每行三个实数x,y,z描述坐标。

\(\color{#0066ff}{输出格式}\)

输出凸包表面积,保留3位小数。

\(\color{#0066ff}{输入样例}\)

4
0 0 0
1 0 0
0 1 0
0 0 1

\(\color{#0066ff}{输出样例}\)

2.366

\(\color{#0066ff}{数据范围与提示}\)

n≤2000

\(\color{#0066ff}{题解}\)

增量法

把每个面,分成正面,反面

先选出3个点(构成一个面)

每次加点

先把当前的点能看见的面全部删除(最后的凸包一定不存在能被某个点看见的面)

然后枚举前面的面中的某两个点,与当前点构成新面,成立则加入

最后的就是凸包的面‘

为了防止共面共线问题,可以在精度允许范围内微调一下坐标

#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {
char ch; int x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const double eps = 1e-9;
const int maxn = 2050;
struct node {
double x, y, z;
node(double x = 0, double y = 0, double z = 0): x(x), y(y), z(z) {}
node operator - (const node &b) const {
return node(x - b.x, y - b.y, z - b.z);
}
node operator ^ (const node &b) const {
return node(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
}
double operator * (const node &b) const {
return x * b.x + y * b.y + z * b.z;
}
void init() {
x = x + ((double)rand() / (double)RAND_MAX - 0.5) * eps * 10;
y = y + ((double)rand() / (double)RAND_MAX - 0.5) * eps * 10;
z = z + ((double)rand() / (double)RAND_MAX - 0.5) * eps * 10;
}
double mo() {
return sqrt(*this * *this);
}
bool jud() {
return fabs(x) <= eps && fabs(y) <= eps && fabs(z) <= eps;
}
}e[maxn]; struct plane {
int v[3];
plane(int a = 0, int b = 0, int c = 0) { v[0] = a, v[1] = b, v[2] = c; }
int &operator [] (const int &b) {
return v[b];
}
node F() const {
return ((e[v[1]] - e[v[0]]) ^ (e[v[2]] - e[v[0]]));
}
bool cansee(node x) const {
return (x - e[v[0]]) * F() > 0;
}
};
int n, cnt;
bool vis[maxn][maxn];
void init() {
n = in();
for(int i = 1; i <= n; i++) {
node o;
scanf("%lf%lf%lf", &o.x, &o.y, &o.z);
for(int j = 1; j <= cnt; j++) if((e[j] - o).jud()) goto cant;
e[++cnt] = o;
cant:;
}
n = cnt;
for(int i = 1; i <= n; i++) e[i].init();
}
double D() {
double ans = 0;
using std::vector;
vector<plane> c;
c.push_back(plane(1, 2, 3));
c.push_back(plane(3, 2, 1));
for(int i = 4; i <= n; i++) {
vector<plane> q;
for(int j = 0; j < (int)c.size(); j++) {
plane t = c[j];
bool flag = t.cansee(e[i]);
if(!flag) q.push_back(c[j]);
for(int k = 0; k < 3; k++)
vis[t[k]][t[(k + 1) % 3]] = flag;
}
for(int j = 0; j < (int)c.size(); j++)
for(int k = 0; k < 3; k++) {
int a = c[j][k], b = c[j][(k + 1) % 3];
if(vis[a][b] != vis[b][a] && vis[a][b])
q.push_back(plane(a, b, i));
}
c = q;
}
for(int i = 0; i < (int)c.size(); i++) ans += c[i].F().mo();
return ans;
} int main() {
init();
printf("%.3f", D() / 2.0);
return 0;
}

P4724 【模板】三维凸包的更多相关文章

  1. luogu P4724 模板 三维凸包

    LINK:三维凸包 一个非常古老的知识点.估计也没啥用. 大体上了解了过程 能背下来就背下来吧. 一个bf:暴力枚举三个点 此时只需要判断所有的点都在这个面的另外一侧就可以说明这个面是三维凸包上的面了 ...

  2. [Luogu4724][模板]三维凸包(增量构造法)

    1.向量点积同二维,x1y1+x2y2+x3y3.向量叉积是行列式形式,(y1z2-z1y2,z1x2-x1z2,x1y2-y1x2). 2.增量构造法: 1)首先定义,一个平面由三个点唯一确定.一个 ...

  3. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  4. hdu4266(三维凸包模板题)

    /*给出三维空间中的n个顶点,求解由这n个顶点构成的凸包表面的多边形个数. 增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况: 1> 在凸包内,则可以跳过 2> ...

  5. POJ3528 HDU3662 三维凸包模板

    POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四 ...

  6. POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心

    题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的 ...

  7. hdu4273Rescue(三维凸包重心)

    链接 模板题已不叫题.. 三维凸包+凸包重心+点到平面距离(体积/点积)  体积-->混合积(先点乘再叉乘) #include <iostream> #include<cstd ...

  8. hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

    新模板 /* HDU 4273 Rescue 给一个三维凸包,求重心到表面的最短距离 模板题:三维凸包+多边形重心+点面距离 */ #include<stdio.h> #include&l ...

  9. bzoj 1209: [HNOI2004]最佳包裹 三维凸包

    1209: [HNOI2004]最佳包裹 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 160  Solved: 58[Submit][Status] ...

  10. bzoj 1964: hull 三维凸包 计算几何

    1964: hull 三维凸包 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 54  Solved: 39[Submit][Status][Discuss ...

随机推荐

  1. 已有项目使用Asset Pipeline管理静态资源

    1.    修改项目中指向静态资源文件的链接 a) 访问静态资源文件 <%= stylesheet_link_tag "application", media: " ...

  2. mybatis---demo1--(单表增删改查)----bai

    实体类: package com.etc.entity; public class News { private int id; private String title; private Strin ...

  3. python web框架 Django基本操作

    django 操作总结! django框架安装: cmd安装: pip3 install django pycharm安装: 在python变量下 搜索 django 安装 创建django项目: c ...

  4. 系统监控磁盘分区 homework

    作业一: 1) 开启Linux系统前添加一块大小为15G的SCSI硬盘 2) 开启系统,右击桌面,打开终端 3) 为新加的硬盘分区,一个主分区大小为5G,剩余空间给扩展分区,在扩展分区上划分1个逻辑分 ...

  5. #测试两种不同的SVM,rbf的核真是太棒了(一种会拐弯的边界)

    from sklearn import datasets import numpy as np X, y = datasets.make_blobs(n_features=2, centers=2) ...

  6. resin容器更改JDK

    更改resin的jdk版本,找到resin的配置文件:Resin\contrib\init.resin文件,找到 JAVA_HOME=@JAVA_HOME@ RESIN_HOME=@resin_hom ...

  7. android手势(gesture)

    需要实现两个接口,OnTouchListener ,OnGestureListener 在接口方法中实现各种事件 详见:http://www.cnblogs.com/JczmDeveloper/p/3 ...

  8. solr的查询语法、查询参数、检索运算符

    转载自:http://martin3000.iteye.com/blog/1328931 1.查询语法 solr的一些查询语法 1.1. 首先假设我的数据里fields有:name, tel, add ...

  9. day69-oracle 21-PLSQL课后作业

  10. Windows系统 为 QT5软件 搭建 OpenCV2 开发环境

    Windows系统 为 QT5软件 搭建 OpenCV2 开发环境 我们的电脑系统:Windows 10 64位 Qt5 软件:Qt 5. 7. 0 OpenCV2 版本:OpenCV2.4.10 1 ...