hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***
新模板
/*
HDU 4273 Rescue
给一个三维凸包,求重心到表面的最短距离
模板题:三维凸包+多边形重心+点面距离
*/ #include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stdlib.h>
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 +(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()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
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();
Point p=hull.barycenter();
double minn=1e20;
for(int i=;i<hull.num;i++)
{
minn=min(minn,hull.ptoface(p,i));
}
printf("%.3lf\n",minn);
}
return ;
}
hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***的更多相关文章
- hdu 4274 2012长春赛区网络赛 树形dp ***
设定每个节点的上限和下限,之后向上更新,判断是否出现矛盾 #include<cstdio> #include<iostream> #include<algorithm&g ...
- hdu 4277 2012长春赛区网络赛 dfs+hashmap ***
hashmap判重大法好 #include<cstdio> #include<iostream> #include<algorithm> #include<c ...
- hdu 4272 2012长春赛区网络赛 dfs暴力 ***
总是T,以为要剪枝,后来发现加个map就行了 #include<cstdio> #include<iostream> #include<algorithm> #in ...
- hdu 4412 2012杭州赛区网络赛 期望
虽然dp方程很好写,就是这个期望不知道怎么求,昨晚的BC也是 题目问题抽象之后为:在一个x坐标轴上有N个点,每个点上有一个概率值,可以修M个工作站, 求怎样安排这M个工作站的位置,使得这N个点都走到工 ...
- hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***
题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙, 每个逮捕队伍在每个城市可以选 ...
- hdu 4293 2012成都赛区网络赛 dp ****
题意:有n个人,可任意分成若干组,然后每个人个各提供一个信息,表示他们组前面有多少人,后面有多少人.问最多有多少个信息是不冲突的. 将n个人看成一组区间,然后每个人的信息可以表示为该人所在组的区间,然 ...
- hdu 4291 2012成都赛区网络赛 矩阵快速幂 ***
分析:假设g(g(g(n)))=g(x),x可能非常大,但是由于mod 10^9+7,所以可以求出x的循环节 求出x的循环节后,假设g(g(g(n)))=g(x)=g(g(y)),即x=g(y),y也 ...
- hdu 4278 2012天津赛区网络赛 数学 *
8进制转为10进制 #include<cstdio> #include<iostream> #include<algorithm> #include<cstr ...
- hdu 4751 2013南京赛区网络赛 二分图判断 **
和以前做过的一个二分图颇为相似,以前的是互相不认识的放在一组,这个是互相认识的,本质上是相同的 是 hdu 2444 #include<cstdio> #include<iostre ...
随机推荐
- apache poi 生成excel
ExcelBuilder.Java package com.coracle.yk.xmanager.util.poi; import com.coracle.yk.xframework.util.Bl ...
- PHP: How to print a debug log?
file_put_contents('php://stderr', print_r("hello ", TRUE)); 转自: http://stackoverflow.com/q ...
- ubuntu14.04 server 安装vmware worktation 12
0) Do the basic system installation of Ubuntu 14.04 LTS (Server or Desktop) 1) wget the installer wg ...
- 【Java】嵌套For循环性能优化案例
参考资料:http://cgs1999.iteye.com/blog/1596671 1 案例描述 某日,在JavaEye上看到一道面试题,题目是这样的:请对以下的代码进行优化 for (int i ...
- Expression表达式树
表达式树表示树状数据结构的代码,树状结构中的每个节点都是一个表达式,例如一个方法调用或类似 x < y 的二元运算 1.利用 Lambda 表达式创建表达式树 Expression<Fun ...
- word to word
Question: For each word, you can get a list of neighbor words by calling getWords(String), find all ...
- ACL
http://man.chinaunix.net/linux/debian/debian_learning/ch01s04.html http://blog.csdn.net/xiangliangyu ...
- Kafka单机环境部署
前面说过Kafka集群环境的部署,现在主要说一下在本地测试中Kafka单机环境的部署,和前面一样首先保证zookeeper服务的正常运行,然后解压并释放kafka安装包,并放到指定位置: tar -x ...
- MySQL 四种事务隔离级的说明
很早之前写的文章,重新回顾和学习下: 按照SQL:1992 事务隔离级别,InnoDB默认是可重复读的(REPEATABLE READ).MySQL/InnoDB 提供SQL标准所描述的所有四个事务隔 ...
- css 自动换行 [英文、数字、中文]
white-space:normal;overflow: auto;table-layout:fixed; word-break: break-all;