P4724 【模板】三维凸包
\(\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 【模板】三维凸包的更多相关文章
- luogu P4724 模板 三维凸包
LINK:三维凸包 一个非常古老的知识点.估计也没啥用. 大体上了解了过程 能背下来就背下来吧. 一个bf:暴力枚举三个点 此时只需要判断所有的点都在这个面的另外一侧就可以说明这个面是三维凸包上的面了 ...
- [Luogu4724][模板]三维凸包(增量构造法)
1.向量点积同二维,x1y1+x2y2+x3y3.向量叉积是行列式形式,(y1z2-z1y2,z1x2-x1z2,x1y2-y1x2). 2.增量构造法: 1)首先定义,一个平面由三个点唯一确定.一个 ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
- hdu4266(三维凸包模板题)
/*给出三维空间中的n个顶点,求解由这n个顶点构成的凸包表面的多边形个数. 增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况: 1> 在凸包内,则可以跳过 2> ...
- POJ3528 HDU3662 三维凸包模板
POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四 ...
- POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心
题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的 ...
- hdu4273Rescue(三维凸包重心)
链接 模板题已不叫题.. 三维凸包+凸包重心+点到平面距离(体积/点积) 体积-->混合积(先点乘再叉乘) #include <iostream> #include<cstd ...
- hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***
新模板 /* HDU 4273 Rescue 给一个三维凸包,求重心到表面的最短距离 模板题:三维凸包+多边形重心+点面距离 */ #include<stdio.h> #include&l ...
- bzoj 1209: [HNOI2004]最佳包裹 三维凸包
1209: [HNOI2004]最佳包裹 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 160 Solved: 58[Submit][Status] ...
- bzoj 1964: hull 三维凸包 计算几何
1964: hull 三维凸包 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 54 Solved: 39[Submit][Status][Discuss ...
随机推荐
- 数据库:MySQL索引背后的数据结构及算法原理【转】
原文:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话 ...
- 解决webpack因新版本打包失败问题--ERROR in multi ./src/main.js ./dist/bundle.js
最近在学习webpack打包过程中遇到的一个问题向大家分享下! 创建了一个webpacksty的目录,目录下放着dist,src子目录,然后通过node环境下,npm init -y 初始化项目出现p ...
- jQuery实现页内锚点平滑跳转
当页面内容长多,导致页面高度过高或过宽是,浏览起来就有点费劲,不过使用了锚点平滑跳转效果可以实现页面的跳转,从而加快速浏览想要浏览的模块.具体做法如下: 首先是菜单(锚点)的写法 <a href ...
- 链接ssh失败问题
Starting sshd:/var/empty/sshd must be owned by root and not group or world-writable. ...
- DAY19-Django之model进阶
QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Entry.objects.all()[ ...
- java之控制多幅图片
package xxj.thread0904; import java.awt.Image; import javax.swing.ImageIcon; import javax.swing.JFra ...
- maven 配置说明
1.坐标 1.1 每一jar文件都有一个唯一坐标.通过坐标可以精确确定是哪个jar 1.2 坐标组成 1.2.1 Group ID : 公司名.公司网址倒写 1.2.2 Artifact ID : 项 ...
- 39、count_rpkm_fpkm_TPM
参考:https://f1000research.com/articles/4-1521/v1 https://www.biostars.org/p/171766/ http://www.rna-se ...
- can基础知识介绍
1.什么是can 2.can的特点 2.物理层特征 我们使用ISO11898标准,物理层特征如图所示 3.帧的种类介绍 实际上有一些帧是有硬件来实现的. 4.数据帧介绍 5.总线仲裁 6.位时序(用于 ...
- Entity Framework Tutorial Basics(30):
CRUD using Stored Procedure: In the previous chapter, we have seen how to get data using a stored pr ...