也是用模板直接套的题目诶

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
using namespace std; const int INF = 0x3f3f3f3f;
const int MAXN = ;
const double eps = 1e-; struct Point{
double x,y,z;
Point(){}
Point(double xx,double yy,double zz):x(xx),y(yy),z(zz){}
//两向量之差
Point operator -(const Point p1){
return Point(x-p1.x,y-p1.y,z-p1.z);
}
//两向量之和
Point operator +(const Point p1){
return Point(x+p1.x,y+p1.y,z+p1.z);
}
//叉乘
Point operator *(const Point p){
return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);
}
Point operator *(double d){
return Point(x*d,y*d,z*d);
}
Point operator / (double d){
return Point(x/d,y/d,z/d);
}
//点乘
double operator ^(Point p){
return (x*p.x+y*p.y+z*p.z);
}
}; struct CH3D{
struct face{
//表示凸包一个面上的三个点的编号
int a,b,c;
//表示该面是否属于最终凸包上的面
bool ok;
};
//初始顶点数
int n;
//初始顶点
Point P[MAXN];
//凸包表面的三角形数
int num;
//凸包表面的三角形
face F[*MAXN];
//凸包表面的三角形
int g[MAXN][MAXN];
//向量长度
double vlen(Point a){
return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}
//叉乘
Point cross(const Point &a,const Point &b,const Point &c){
return Point((b.y-a.y)*(c.z-a.z)-(b.z-a.z)*(c.y-a.y),
(b.z-a.z)*(c.x-a.x)-(b.x-a.x)*(c.z-a.z),
(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x)
);
}
//三角形面积*2
double area(Point a,Point b,Point c){
return vlen((b-a)*(c-a));
}
//四面体有向体积*6
double volume(Point a,Point b,Point c,Point d){
return (b-a)*(c-a)^(d-a);
}
//正:点在面同向
double dblcmp(Point &p,face &f){
Point m=P[f.b]-P[f.a];
Point n=P[f.c]-P[f.a];
Point t=p-P[f.a];
return (m*n)^t;
}
void deal(int p,int a,int b){
int f=g[a][b];//搜索与该边相邻的另一个平面
face add;
if(F[f].ok){
if(dblcmp(P[p],F[f])>eps)
dfs(p,f);
else{
add.a=b;
add.b=a;
add.c=p;//这里注意顺序,要成右手系
add.ok=true;
g[p][b]=g[a][p]=g[b][a]=num;
F[num++]=add;
}
}
}
//递归搜索所有应该从凸包内删除的面
void dfs(int p,int now){
F[now].ok=;
deal(p,F[now].b,F[now].a);
deal(p,F[now].c,F[now].b);
deal(p,F[now].a,F[now].c);
}
bool same(int s,int t){
Point &a=P[F[s].a];
Point &b=P[F[s].b];
Point &c=P[F[s].c];
return fabs(volume(a,b,c,P[F[t].a]))<eps &&
fabs(volume(a,b,c,P[F[t].b]))<eps &&
fabs(volume(a,b,c,P[F[t].c]))<eps;
}
//构建三维凸包
void create(){
int i,j,tmp;
face add;
num=;
if(n<)return;
//**********************************************
//此段是为了保证前四个点不共面
bool flag=true;
for(i=;i<n;i++){
if(vlen(P[]-P[i])>eps){
swap(P[],P[i]);
flag=false;
break;
}
}
if(flag)return;
flag=true;
//使前三个点不共线
for(i=;i<n;i++){
if(vlen((P[]-P[])*(P[]-P[i]))>eps){
swap(P[],P[i]);
flag=false;
break;
}
}
if(flag)return;
flag=true;
//使前四个点不共面
for(int i=;i<n;i++){
if(fabs((P[]-P[])*(P[]-P[])^(P[]-P[i]))>eps){
swap(P[],P[i]);
flag=false;
break;
}
}
if(flag)return;
//*****************************************
for(i=;i<;i++){
add.a=(i+)%;
add.b=(i+)%;
add.c=(i+)%;
add.ok=true;
if(dblcmp(P[i],add)>)swap(add.b,add.c);
g[add.a][add.b]=g[add.b][add.c]=g[add.c][add.a]=num;
F[num++]=add;
}
for(i=;i<n;i++){
for(j=;j<num;j++){
if(F[j].ok&&dblcmp(P[i],F[j])>eps){
dfs(i,j);
break;
}
}
}
tmp=num;
for(i=num=;i<tmp;i++)
if(F[i].ok)
F[num++]=F[i];
}
//表面积
double area(){
double res=;
if(n==){
Point p=cross(P[],P[],P[]);
res=vlen(p)/2.0;
return res;
}
for(int i=;i<num;i++)
res+=area(P[F[i].a],P[F[i].b],P[F[i].c]);
return res/2.0;
}
double volume(){
double res=;
Point tmp(,,);
for(int i=;i<num;i++)
res+=volume(tmp,P[F[i].a],P[F[i].b],P[F[i].c]);
return fabs(res/6.0);
}
//表面三角形个数
int triangle(){
return num;
}
//表面多边形个数
int polygon(){
int i,j,res,flag;
for(i=res=;i<num;i++){
flag=;
for(j=;j<i;j++)
if(same(i,j)){
flag=;
break;
}
res+=flag;
}
return res;
}
//三维凸包重心
Point barycenter(){
Point ans(,,),o(,,);
double all=;
for(int i=;i<num;i++){
double vol=volume(o,P[F[i].a],P[F[i].b],P[F[i].c]);
ans=ans+(o+P[F[i].a]+P[F[i].b]+P[F[i].c])/4.0*vol;
all+=vol;
}
ans=ans/all;
return ans;
}
//点到面的距离
double ptoface(Point p,int i){
return fabs(volume(P[F[i].a],P[F[i].b],P[F[i].c],p)/vlen((P[F[i].b]-P[F[i].a])*(P[F[i].c]-P[F[i].a])));
}
};
CH3D hull;
int main(){
while(scanf("%d",&hull.n)==){
for(int i=;i<hull.n;i++){
scanf("%lf%lf%lf",&hull.P[i].x,&hull.P[i].y,&hull.P[i].z);
}
hull.create();
printf("%.3f\n",hull.area());
}
return ;
}

POJ 3528 求三维凸包表面积的更多相关文章

  1. POJ 3528--Ultimate Weapon(三维凸包)

    Ultimate Weapon Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2430   Accepted: 1173 ...

  2. BZOJ1209 最佳包裹 (三维凸包 增量法)

    题意 求三维凸包的表面积. N≤100N\le100N≤100 题解 暴力往当前的凸包里加点.O(n2)O(n^2)O(n2).题解详见大佬博客 扰动函数shakeshakeshake是为了避免四点共 ...

  3. BZOJ1209 [HNOI2004]最佳包裹 三维凸包 计算几何

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1209 题目概括 给出立体的n个点.求三维凸包面积. 题解 增量法,看了一天,还是没有完全懂. 上板 ...

  4. luogu P4724 模板 三维凸包

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

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

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

  6. 三维凸包求其表面积(POJ3528)

    Ultimate Weapon Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2074   Accepted: 989 D ...

  7. poj 3608 旋转卡壳求不相交凸包最近距离;

    题目链接:http://poj.org/problem?id=3608 #include<cstdio> #include<cstring> #include<cmath ...

  8. 三维凸包求凸包表面的个数(HDU3662)

    3D Convex Hull Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. 三维凸包求重心到面的最短距离(HDU4273)

    http://acm.hdu.edu.cn/showproblem.php?pid=4273 Rescue Time Limit: 2000/1000 MS (Java/Others)    Memo ...

随机推荐

  1. app微信支付服务器端php demo

    class Wxpay { /* 配置参数 */ private $config = array( 'appid' => "wxc92b12277f277355", /*微信 ...

  2. C++ 面向对象学习2 构造方法

    Date.h #ifndef DATE_H #define DATE_H class Date{ public: Date(,,);//自定义了构造方法 会覆盖掉默认的无参构造方法 void setD ...

  3. hive 0.10 0.11新增特性综述

    我们的hive版本升迁经历了0.7.1 -> 0.8.1 -> 0.9.0,并且线上shark所依赖的hive版本也停留在0.9.0上,在这些版本上有我们自己的bug fix patch和 ...

  4. word中创建文本框

    word中创建文本框         在插入中点击"文本框"选项卡,例如以下图所看到的:        手工加入自己想要的文本框格式,然后选择所创建的文本框,在工具栏处会发现多了一 ...

  5. STL之string插入

    #include <iostream> #include <string> using namespace std; int main() { string s("h ...

  6. 移动Web开发小技巧

    移动Web开发小技巧 添加到主屏后的标题(IOS) name="apple-mobile-web-app-title" content="标题"> 启用  ...

  7. 基于表单的身份验证(FBA)

    https://technet.microsoft.com/zh-cn/library/ee806890(office.15).aspx http://www.tuicool.com/articles ...

  8. ADO.NET(一) 空间 ADO.NET结构 命名空间(车延禄) System.Data—— 所有的一般数据访问类 S(转载)

    ADO.NET(一) 空间   ADO.NET结构 命名空间(车延禄)System.Data—— 所有的一般数据访问类System.Data.Common—— 各个数据提供程序共享(或重写)的类Sys ...

  9. Orchard 添加搜索栏

    Orchard 提供索引和搜索的功能. 索引功能需要开启 Indexing 模块, 同时我们要开启Lucene 模块(做实际检索工作的东西). 然后还要开启Search模块(调用Lucene 查询然后 ...

  10. SPOJ8222 Substrings( 后缀自动机 + dp )

    题目大意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.F(1)..F(Length(S)) 建出SAM, 然后求出Right, 求Right可以按拓扑序dp..Right ...