新模板

 /*
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长春赛区网络赛 三维凸包中心到最近面距离 ***的更多相关文章

  1. hdu 4274 2012长春赛区网络赛 树形dp ***

    设定每个节点的上限和下限,之后向上更新,判断是否出现矛盾 #include<cstdio> #include<iostream> #include<algorithm&g ...

  2. hdu 4277 2012长春赛区网络赛 dfs+hashmap ***

    hashmap判重大法好 #include<cstdio> #include<iostream> #include<algorithm> #include<c ...

  3. hdu 4272 2012长春赛区网络赛 dfs暴力 ***

    总是T,以为要剪枝,后来发现加个map就行了 #include<cstdio> #include<iostream> #include<algorithm> #in ...

  4. hdu 4412 2012杭州赛区网络赛 期望

    虽然dp方程很好写,就是这个期望不知道怎么求,昨晚的BC也是 题目问题抽象之后为:在一个x坐标轴上有N个点,每个点上有一个概率值,可以修M个工作站, 求怎样安排这M个工作站的位置,使得这N个点都走到工 ...

  5. hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***

    题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙,          每个逮捕队伍在每个城市可以选 ...

  6. hdu 4293 2012成都赛区网络赛 dp ****

    题意:有n个人,可任意分成若干组,然后每个人个各提供一个信息,表示他们组前面有多少人,后面有多少人.问最多有多少个信息是不冲突的. 将n个人看成一组区间,然后每个人的信息可以表示为该人所在组的区间,然 ...

  7. 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也 ...

  8. hdu 4278 2012天津赛区网络赛 数学 *

    8进制转为10进制 #include<cstdio> #include<iostream> #include<algorithm> #include<cstr ...

  9. hdu 4751 2013南京赛区网络赛 二分图判断 **

    和以前做过的一个二分图颇为相似,以前的是互相不认识的放在一组,这个是互相认识的,本质上是相同的 是 hdu 2444 #include<cstdio> #include<iostre ...

随机推荐

  1. Eclipse不给提示no default proposals

    解决方法: (1),找到工程所在的workspace,删除.metadata配置文件. (2),启动eclipse,重新定位到先前的workspace目录置,重建同名工程(不要删除原来的工程,只要建立 ...

  2. ASP.NET MVC 路由调试工具Router Debugger

    直接上图 安装好手动启用或关闭 我开始调试我之前程序中由于路由遇到的问题 当发出 http://localhost:2362/109.html 这样请求, 我的意图是想Article的Details被 ...

  3. 一个Try多个Catch需要注意的事项

    一个程序包含一个try块和两个catch块,两个catch子句都有能力捕捉一个try块发出的异常,若两个catch子句次序不同时程序结果会发生变化吗? 一个try块后有两个catch块,这很正常,因为 ...

  4. 【leetcode】Fraction to Recurring Decimal

    Fraction to Recurring Decimal Given two integers representing the numerator and denominator of a fra ...

  5. CentOS7下安装soaplib

    测试安装 cd ENV . bin/activate yum install libxml2-devel libxslt-devel pip install soaplib 安装中遇到的问题: Uni ...

  6. yum简单安装salt master与minion

    首先得先安装epel的yum源: rpm -ivh http://mirrors.skyshe.cn/epel/6/x86_64/epel-release-6-8.noarch.rpm 1.SaltS ...

  7. shell变量判空几种方法

    强烈声明:关于对数字的比较以及判断是否为空 最好在外层添加""引起来,这样可以避免空与其他字符比较时报错的问题. 1. 变量通过" "引号引起来 #!/bin/ ...

  8. Xcode无法启动ios模拟器的问题

    一.问题描述 开发过程需要来回切换ios模拟器调试程序,开始在iPhone 4s下调试,然后切换到iPhone 6s Plus,再切换回iPhone 4s,遇到无法启动ios模拟器.错误提示如下: 二 ...

  9. BestCoder21 1002.Formula 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5139 题目意思:给出一个数 n,求出 f(n). 可以发现有以下规律: f(1) = 1! f(2) ...

  10. ubuntu下安装mysql

    现在的软件越来越好安装,尤其是在ubuntu下安装软件,更是没有技巧,只需要在联网的情况下使用apt-get inatll 即可.在决定安装mysql之前,要先确定系统是否已经安装mysql.如下图: ...