hdu4266(三维凸包模板题)
- /*给出三维空间中的n个顶点,求解由这n个顶点构成的凸包表面的多边形个数.
- 增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况:
- 1> 在凸包内,则可以跳过
- 2> 在凸包外,找到从这个点可以"看见"的面,删除这些面,
- 然后对于一边没有面的线段,和新加的这个点新建一个面,至于这个点可以看见的面,
- 就是求出这个面的方程(可以直接求法向量).
- */
- #include<iostream>
- #include<cmath>
- #include<cstring>
- #include<cstdlib>
- #include<algorithm>
- using namespace std;
- 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 *(Point p) //叉乘
- {
- return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);
- }
- double operator ^(Point p) //点乘
- {
- return (x*p.x+y*p.y+z*p.z);
- }
- void read()
- {
- scanf("%lf%lf%lf",&x,&y,&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.x-a.x)*(c.z-a.z)
- -(b.z-a.z)*(c.x-a.x)),(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x));
- }
- double area(Point a,Point b,Point c) //三角形面积*2
- {
- return vlen((b-a)*(c-a));
- }
- double volume(Point a,Point b,Point c,Point d) //四面体有向体积*6
- {
- 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=;
- 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 solve() //构建三维凸包
- {
- int i,j,tmp;
- face add;
- bool flag=true;
- num=;
- if(n<)
- return;
- 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(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=0.0;
- 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=0.0;
- 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 getcent()//求凸包质心
- {
- Point ans(,,),temp=P[F[].a];
- double v = 0.0,t2;
- for(int i=;i<num;i++){
- if(F[i].ok == true){
- Point p1=P[F[i].a],p2=P[F[i].b],p3=P[F[i].c];
- t2 = volume(temp,p1,p2,p3)/6.0;//体积大于0,也就是说,点 temp 不在这个面上
- if(t2>){
- ans.x += (p1.x+p2.x+p3.x+temp.x)*t2;
- ans.y += (p1.y+p2.y+p3.y+temp.y)*t2;
- ans.z += (p1.z+p2.z+p3.z+temp.z)*t2;
- v += t2;
- }
- }
- }
- ans.x /= (*v); ans.y /= (*v); ans.z /= (*v);
- return ans;
- }
- double function(Point fuck){//点到凸包上的最近距离(枚举每个面到这个点的距离)
- double min=;
- for(int i=;i<num;i++){
- if(F[i].ok==true){
- Point p1=P[F[i].a] , p2=P[F[i].b] , p3=P[F[i].c];
- double a = ( (p2.y-p1.y)*(p3.z-p1.z)-(p2.z-p1.z)*(p3.y-p1.y) );
- double b = ( (p2.z-p1.z)*(p3.x-p1.x)-(p2.x-p1.x)*(p3.z-p1.z) );
- double c = ( (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x) );
- double d = ( -(a*p1.x+b*p1.y+c*p1.z) );
- double temp = fabs(a*fuck.x+b*fuck.y+c*fuck.z+d)/sqrt(a*a+b*b+c*c);
- if(temp<min)min = temp;
- }
- }
- return min;
- }
- };
- int main()
- {
- int n;
- while(scanf("%d",&n) && n)
- {
- CH3D hull;
- hull.n=n;
- for(int i=;i<n;i++)
- {
- hull.P[i].read();
- }
- hull.solve();
- int q;
- scanf("%d",&q);
- for(int i=;i<q;i++)
- {
- Point tp;
- tp.read();
- double ans=1e9;
- ans = min(ans, hull.function(tp) );
- printf("%.4lf\n",ans);
- }
- }
- return ;
- }
求点到三维凸包的最小距离,直接用模板暴力枚举即可。
hdu4266(三维凸包模板题)的更多相关文章
- POJ3528 HDU3662 三维凸包模板
POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四 ...
- POJ 3348 Cows | 凸包模板题
题目: 给几个点,用绳子圈出最大的面积养牛,输出最大面积/50 题解: Graham凸包算法的模板题 下面给出做法 1.选出x坐标最小(相同情况y最小)的点作为极点(显然他一定在凸包上) 2.其他点进 ...
- hdu 1348 Wall(凸包模板题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1348 Wall Time Limit: 2000/1000 MS (Java/Others) M ...
- POJ:Dungeon Master(三维bfs模板题)
Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16748 Accepted: 6522 D ...
- HDU 1392 凸包模板题,求凸包周长
1.HDU 1392 Surround the Trees 2.题意:就是求凸包周长 3.总结:第一次做计算几何,没办法,还是看了大牛的博客 #include<iostream> #inc ...
- POJ 1113 凸包模板题
上模板. #include <cstdio> #include <cstring> #include <iostream> #include <algorit ...
- bzoj1670 Usaco2006 Building the Moat护城河的挖掘 [凸包模板题]
Description 为了防止口渴的食蚁兽进入他的农场,Farmer John决定在他的农场周围挖一条护城河.农场里一共有N(8<=N<=5,000)股泉水,并且,护城河总是笔直地连接在 ...
- UVA 11769 All Souls Night 的三维凸包要求的表面面积
主题链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=2869">点击打开链接 求给定的 ...
- hdu 1348 凸包模板
http://acm.hdu.edu.cn/showproblem.php?pid=1348 造城墙问题,求出凸包加上一圈圆的周长即可 凸包模板题 #include <cstdio> #i ...
随机推荐
- javascript - 实现jquery类似的$调用方法
var $ = { name: function (name) { return name; }, age: function (age) { return age; }, numCount: fun ...
- Android项目-几种常见的应用架构
android两种Tab分页的方式:TabActivity和ActivityGroup http://www.fengfly.com/plus/view-209429-1.html 1.单个Activ ...
- WP8学习笔记:如何在页面显示前自动转向到其他页面
在本次修练开始之前,我们除了预设的 MainPage页面外,也另外新增了一个 Login页面,如下图示: MainPage.xaml页面长这样 Login.xaml页面长这样 因为我们的需求是要求使用 ...
- 同时安装office2016与visio2016的实现过程
visio 2016安装问题 同时安装office2016与visio2016的实现过程 visio2016 but failed
- centos mysql iptables配置
在CentOS系统中防火墙默认是阻止3306端口的,我们要是想访问mysql数据库,我们需要这个端口,命令如下: iptables -I INPUT -p tcp --dport 3036 -j AC ...
- Leetcode--easy系列3
#26 Remove Duplicates from Sorted Array Given a sorted array, remove the duplicates in place such th ...
- C++ 内存泄漏
1. 内存泄漏: 在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况. 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前 ...
- >/dev/null 2>&1的作用
1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/dev/null" 2 表示stderr标准错误 &am ...
- Unity学习笔记 - UI System(一)
转载请注明出处: EnigmaJJ http://www.cnblogs.com/twjcnblog/p/5850648.html 术语 Canvas是Unity的原生组件,Unity的渲染系统使用C ...
- deepin下安装python的Tkinter库
在Linux下,如果需要编写界面应用,并且此界面应用对性能的要求不是很高,一般可以使用Python解决.Python中可以使用自带的Tkinter库或者是第三方的Wxpython库,当然Tkinter ...