1964: hull 三维凸包

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 54  Solved: 39
[Submit][Status][Discuss]

Description

三维凸包问题是一个基础的三维计算几何问题,不过这次你只需要做一个简单版的三维凸包问题就行了。

Input

输入数据一共有若干行,每行三个整数,表示一个点的坐标。点的个数为五个。

Output

输出一个实数,保留两位小数,表示三维凸包的体积。

Sample Input

0 0 0
2 0 0
0 2 0
2 2 0
1 1 1

Sample Output

1.33

HINT

对于所有数据,坐标范围在[0,100]*[0,100]*[0,100]。

  直接水过,不过网上的三维凸包的标程一个比一个不靠谱,由一组数据拍出来,加上我的程序,三个程序三个答案。整个人都不好了。

  枚举一个面,使得剩下两个点与这条面组成四面体的有向体积符号不同,则两点在面的两侧,计算即可。

  四面体的计算公式是三个向量组成的矩阵行列式的1/6.

  这是居然我的第一个三维算几题。

  另外,这个方法的正确性我还是比较怀疑,因为存在数据是他和网上的三维算几模板矛盾,虽然大部分可以看出是网上的程序的问题,但是居然他与我自己写的版有矛盾,就姑且把它当成骗分暴力吧。(最后有三维凸包程序)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
#define MAXN 10
typedef double real;
struct point
{
real x,y,z;
point(real x,real y,real z):x(x),y(y),z(z){}
point(){}
void read()
{
scanf("%lf %lf %lf",&x,&y,&z);
}
}pl[MAXN];;
real area(point p1,point p2,point p3)
{
return (p1.x*p2.y*p3.z + p1.z*p2.x*p3.y + p1.y*p2.z*p3.x
-p1.x*p2.z*p3.y - p1.z*p2.y*p3.x - p1.y*p2.x*p3.z)/;
}
point operator -(point p1,point p2)
{
return point(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z);
}
typedef point line; bool vis[MAXN];
int main()
{
freopen("input.txt","r",stdin);
for (int i=;i<;i++)
{
pl[i].read();
}
// printf("%.2lf\n",area(pl[1]-pl[0],pl[2]-pl[0],pl[3]-pl[0]));
real ans=;
real s1,s2,s3;
for (int a=;a<;a++)
{
vis[a]=true;
for (int b=;b<;b++)
{
if (vis[b])continue;
vis[b]=true;
for (int c=;c<;c++)
{
if (vis[c])continue;
vis[c]=true;
for (int d=;d<;d++)
{
if (vis[d])continue;
vis[d]=true;
for (int e=;e<;e++)
{
if (vis[e])continue;
vis[e]=true;
s3=abs(s1=area(pl[c]-pl[a],pl[b]-pl[a],pl[d]-pl[a]))+abs(s2=area(pl[c]-pl[a],pl[b]-pl[a],pl[e]-pl[a]));
if (s1*s2>)
{
vis[e]=false;continue;
}
if (s1== && s2==)
{
vis[e]=false;continue;
}
ans=max(ans,s3);
vis[e]=false;
}
vis[d]=false;
}
vis[c]=false;
}
vis[b]=false;
}
vis[a]=false;
}
printf("%.2lf\n",ans);
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<assert.h>
#include<vector>
using namespace std;
#define MAXN 120
#define eps 1e-8
typedef double real;
inline int sgn(real x)
{
if (abs(x)<eps)return ;
return x<?-:;
}
struct point
{
real x,y,z;
point(real x,real y,real z):x(x),y(y),z(z){}
point(){}
int read()
{
return scanf("%lf %lf %lf\n",&x,&y,&z);
}
void noise()
{
x+=(real)(rand()%-)/*eps;
y+=(real)(rand()%-)/*eps;
z+=(real)(rand()%-)/*eps;
}
real len()
{
return sqrt(x*x+y*y+z*z);
}
};
typedef point vect;
struct line
{
point ps;
real x,y,z;
line(){}
line(point p1,point p2)
{
ps=p1;
x=p2.x-p1.x;
y=p2.y-p1.y;
z=p2.z-p1.z;
}
line(point ps,real x,real y,real z):ps(ps),x(x),y(y),z(z){}
};
vect xmul(line l1,line l2)
{
return vect(l1.y*l2.z-l1.z*l2.y,l1.z*l2.x-l1.x*l2.z,l1.x*l2.y-l1.y*l2.x);
}
real volume(line l1,line l2,line l3)
{
return + l1.x*l2.y*l3.z - l1.x*l2.z*l3.y
- l1.y*l2.x*l3.z + l1.y*l2.z*l3.x
+ l1.z*l2.x*l3.y - l1.z*l2.y*l3.x;
}
//+1 2 3
//-1 3 2
//-2 1 3
//+2 3 1
//+3 1 2
//-3 2 1
struct surface
{
point ps;
real x1,y1,z1;
real x2,y2,z2;
surface(){}
surface(point p1,point p2,point p3)
{
ps=p1;
x1=p2.x-p1.x,y1=p2.y-p1.y,z1=p2.z-p1.z;
x2=p3.x-p1.x,y2=p3.y-p1.y,z2=p3.z-p1.z;
}
real volume(point pt)
{
return ::volume(line(ps,pt),line(ps,x1,y1,z1),line(ps,x2,y2,z2));
}
vect nvect()
{
return xmul(line(ps,x1,y1,z1),line(ps,x2,y2,z2));
}
void reverse()
{
swap(x1,x2);
swap(y1,y2);
swap(z1,z2);
}
};
point pl[MAXN];
struct face
{
int pt[];
face(int x,int y,int z)
{
pt[]=x;pt[]=y;pt[]=z;
}
surface ToSurface()
{
return surface(pl[pt[]],pl[pt[]],pl[pt[]]);
}
void print()
{
printf("Face:%d %d %d\n",pt[],pt[],pt[]);
}
};
vector<face> cc;
vector<pair<int,int> > chs;
bool status[MAXN][MAXN];
int main()
{
freopen("input.txt","r",stdin);
int n=;
while (~pl[n++].read());
n--;
for (int i=;i<n;i++)
pl[i].noise();
/* for (int i=0;i<n;i++)
swap(pl[rand()%n],pl[rand()%n]);*/
cc.push_back(face(,,));
cc.push_back(face(,,));
for (int i=;i<;i++)
status[i][(i+)%]=true;
for (int i=;i<;i++)
status[i%][i-]=true;
for (int i=;i<n;i++)
{
//for (int j=0;j<cc.size();j++)cc[j].print(); printf("\n");
chs.clear();
for (int j=;j<cc.size();j++)
{
if (cc[j].ToSurface().volume(pl[i])<)
{
for (int k=;k<;k++)
{
status[cc[j].pt[k]][cc[j].pt[(k+)%]]=false;
chs.push_back(make_pair(cc[j].pt[k],cc[j].pt[(k+)%]));
}
swap(cc[j],cc[cc.size()-]);
cc.pop_back();
j--;
}
}
for (int j=;j<chs.size();j++)
{
if (!status[chs[j].first][chs[j].second] && status[chs[j].second][chs[j].first])continue;
chs[j]=chs[chs.size()-];
j--;
chs.pop_back();
}
for (int j=;j<chs.size();j++)
{
cc.push_back(face(i,chs[j].first,chs[j].second));
status[i][chs[j].first]=status[chs[j].first][chs[j].second]=status[chs[j].second][i]=true;
}
for (int j=;j<n;j++)
for (int k=;k<n;k++)
assert(!(status[j][k]^status[k][j]));
}
//for (int j=0;j<cc.size();j++)cc[j].print(); printf("\n");
real ans=;
for (int i=;i<cc.size();i++)
{
ans+=cc[i].ToSurface().volume(point(,,))/;
}
printf("%.2lf\n",abs(ans));
}

bzoj 1964: hull 三维凸包 计算几何的更多相关文章

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

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

  2. [BZOJ1964]hull 三维凸包:计算几何

    分析 发现自己并不会计算几何. 所以先引用一下这位dalao的博客. 二维平面四个点求凸包面积->任选三个点面积之和/2 三维平面五个点求凸包体积->任选四个点体积之和/2 二维平面三个点 ...

  3. bzoj1964: hull 三维凸包

    传送门 二维平面四个点求凸包面积->任选三个点面积之和/2 三维平面五个点求凸包体积->任选四个点体积之和/2 二维平面三个点面积->二个二维向量行列式值的绝对值/2 三维平面四个点 ...

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

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

  5. 洛谷P4502 [ZJOI2018]保镖(计算几何+三维凸包)

    题面 传送门 题解 我对计蒜几盒一无所知 顺便\(xzy\)巨巨好强 前置芝士 三维凸包 啥?你不会三维凸包?快去把板子写了->这里 欧拉公式 \[V-E+F=2\] \(V:vertex\)顶 ...

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

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

  7. hdu4273Rescue(三维凸包重心)

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

  8. hdu4449Building Design(三维凸包+平面旋转)

    链接 看了几小时也没看懂代码表示的何意..无奈下来问问考研舍友. 还是考研舍友比较靠谱,分分钟解决了我的疑问. 可能三维的东西在纸面上真的不好表示,网上没有形象的题解,只有简单"明了&quo ...

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

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

随机推荐

  1. Java基础知识强化之IO流笔记45:IO流练习之 把集合中的数据存储到文本文件案例

    1. 把集合中的数据存储到文本文件案例:    需求:把ArrayList集合中的字符串数据存储到文本文件 ? (1)分析:通过题目的意思我们可以知道如下的一些内容,ArrayList集合里存储的是字 ...

  2. javascript笔记09:javascript的下拉式导航菜单

    <!DOCTYPE html> <html> <body> <script> function hideAll() { for(i=0;i<odi ...

  3. Debian 6解决中文乱码

    DEBIAN下中文显示 一.首先检查LOCALE情况 说明:DEBIAN因为基于GNU所以,对不同地域进行了不同的包支持,以LOCALE形式存在. 1.挂载ISO文件包,前8个ISO包就可以(这里不在 ...

  4. JVM中的Stack和Heap

    Stack: 是内存指令区.Java基本数据类型,Java指令代码,常量都保存在stack中,方法是指令也保存在stack中. 由于stack是内存是顺序分配,而且定长,不存在内存回收问题.存取速度快 ...

  5. %s 与 %0s在 verilog中的区别

    what is different between %s and %0s?(%s和%零s) %s prints the string as it is with spaces at the begin ...

  6. <转载>解决div里面img的缝隙问题

    转载自:http://blog.sina.com.cn/s/blog_9fd5b6df01013mld.html   练习切图时发现img和父级div之间总是有2px空隙(chrome),上网搜索解决 ...

  7. css-position的相关用法

    简介 position用于固定位置,是尤为重要的一个属性 其值可以为: static: 默认值,忽略top, bottom, left, right 或者 z-index 声明 relative: 相 ...

  8. Unity3D 之3D动画机设置

    新建一个动画机 然后创建一些动画的属性 每根线都是一个动画到下一个动画的转变,动画的转变是基于条件的. 1.通过建立Parameters设定动画的转换条件 2.右边的Conditions设定可以设定是 ...

  9. mysql学习笔记2

    drop database 数据库名称;————删除数据库 show columns from 数据表名[from 数据库名]:(或者 show columns from 数据库.数据表名:)———— ...

  10. Java基础巩固----泛型

    注:参考书籍:Java语言程序设计.本篇文章为读书笔记,供大家参考学习使用 1.使用泛型的主要优点是能够在编译时而不是在运行时检查出错误,提高了代码的安全性和可读性,同时也提高了代码的复用性. 1.1 ...