题意:给两个凸包,凸包能旋转,求凸包重心之间的最短距离。

思路:显然两个凸包贴在一起时,距离最短。所以,先求重心,再求重心到各个面的最短距离。

三维凸包+重心求法

重心求法:在凸包内,任意枚举一点,在与凸包其他一个面组成一个三棱锥。求出每个三棱锥的重心,把三棱锥等效成一个个质点,再求整体的重心。

 #include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std; const double eps = 1e-;
int dcmp(double x)
{
if(fabs(x) < eps) return ;
else return x < ? - : ;
} struct Point3
{
double x, y, z;
Point3(double x=, double y=, double z=):x(x),y(y),z(z) { }
}; typedef Point3 Vector3; Vector3 operator + (const Vector3& A, const Vector3& B)
{
return Vector3(A.x+B.x, A.y+B.y, A.z+B.z);
}
Vector3 operator - (const Point3& A, const Point3& B)
{
return Vector3(A.x-B.x, A.y-B.y, A.z-B.z);
}
Vector3 operator * (const Vector3& A, double p)
{
return Vector3(A.x*p, A.y*p, A.z*p);
}
Vector3 operator / (const Vector3& A, double p)
{
return Vector3(A.x/p, A.y/p, A.z/p);
} bool operator == (const Point3& a, const Point3& b)
{
return dcmp(a.x-b.x) == && dcmp(a.y-b.y) == && dcmp(a.z-b.z) == ;
} Point3 read_point3()
{
Point3 p;
scanf("%lf%lf%lf", &p.x, &p.y, &p.z);
return p;
} double Dot(const Vector3& A, const Vector3& B)
{
return A.x*B.x + A.y*B.y + A.z*B.z;
}
double Length(const Vector3& A)
{
return sqrt(Dot(A, A));
}
double Angle(const Vector3& A, const Vector3& B)
{
return acos(Dot(A, B) / Length(A) / Length(B));
}
Vector3 Cross(const Vector3& A, const Vector3& B)
{
return Vector3(A.y*B.z - A.z*B.y, A.z*B.x - A.x*B.z, A.x*B.y - A.y*B.x);
}
double Area2(const Point3& A, const Point3& B, const Point3& C)
{
return Length(Cross(B-A, C-A));
}
double Volume6(const Point3& A, const Point3& B, const Point3& C, const Point3& D)
{
return Dot(D-A, Cross(B-A, C-A));
}
Point3 Centroid(const Point3& A, const Point3& B, const Point3& C, const Point3& D)
{
return (A + B + C + D)/4.0;
} double rand01()
{
return rand() / (double)RAND_MAX;
}
double randeps()
{
return (rand01() - 0.5) * eps;
} Point3 add_noise(const Point3& p)
{
return Point3(p.x + randeps(), p.y + randeps(), p.z + randeps());
} struct Face
{
int v[];
Face(int a, int b, int c)
{
v[] = a;
v[] = b;
v[] = c;
}
Vector3 Normal(const vector<Point3>& P) const
{
return Cross(P[v[]]-P[v[]], P[v[]]-P[v[]]);
}
// f是否能看见P[i]
int CanSee(const vector<Point3>& P, int i) const
{
return Dot(P[i]-P[v[]], Normal(P)) > ;
}
}; // 增量法求三维凸包
// 注意:没有考虑各种特殊情况(如四点共面)。实践中,请在调用前对输入点进行微小扰动
vector<Face> CH3D(const vector<Point3>& P)
{
int n = P.size();
vector<vector<int> > vis(n);
for(int i = ; i < n; i++) vis[i].resize(n); vector<Face> cur;
cur.push_back(Face(, , )); // 由于已经进行扰动,前三个点不共线
cur.push_back(Face(, , ));
for(int i = ; i < n; i++)
{
vector<Face> next;
// 计算每条边的“左面”的可见性
for(int j = ; j < cur.size(); j++)
{
Face& f = cur[j];
int res = f.CanSee(P, i);
if(!res) next.push_back(f);
for(int k = ; k < ; k++) vis[f.v[k]][f.v[(k+)%]] = res;
}
for(int j = ; j < cur.size(); j++)
for(int k = ; k < ; k++)
{
int a = cur[j].v[k], b = cur[j].v[(k+)%];
if(vis[a][b] != vis[b][a] && vis[a][b]) // (a,b)是分界线,左边对P[i]可见
next.push_back(Face(a, b, i));
}
cur = next;
}
return cur;
} struct ConvexPolyhedron
{
int n;
vector<Point3> P, P2;
vector<Face> faces; bool read()
{
if(scanf("%d", &n) != ) return false;
P.resize(n);
P2.resize(n);
for(int i = ; i < n; i++)
{
P[i] = read_point3();
P2[i] = add_noise(P[i]);
}
faces = CH3D(P2);
return true;
} Point3 centroid()
{
Point3 C = P[];
double totv = ;
Point3 tot(,,);
for(int i = ; i < faces.size(); i++)
{
Point3 p1 = P[faces[i].v[]], p2 = P[faces[i].v[]], p3 = P[faces[i].v[]];
double v = -Volume6(p1, p2, p3, C);
totv += v;
tot = tot + Centroid(p1, p2, p3, C)*v;
}
return tot / totv;
} double mindist(Point3 C)
{
double ans = 1e30;
for(int i = ; i < faces.size(); i++)
{
Point3 p1 = P[faces[i].v[]], p2 = P[faces[i].v[]], p3 = P[faces[i].v[]];
ans = min(ans, fabs(-Volume6(p1, p2, p3, C) / Area2(p1, p2, p3)));
}
return ans;
}
}; int main()
{
int n, m;
ConvexPolyhedron P1, P2;
while(P1.read() && P2.read())
{
Point3 C1 = P1.centroid();
double d1 = P1.mindist(C1);
Point3 C2 = P2.centroid();
double d2 = P2.mindist(C2);
printf("%.8lf\n", d1+d2);
}
return ;
}

uvalive 4589 Asteroids的更多相关文章

  1. poj 3862 && LA 4589 Asteroids (三维凸包+多面体重心)

    3862 -- Asteroids ACM-ICPC Live Archive 用给出的点求出凸包的重心,并求出重心到多边形表面的最近距离. 代码如下: #include <cstdio> ...

  2. UVALive - 4108 SKYLINE[线段树]

    UVALive - 4108 SKYLINE Time Limit: 3000MS     64bit IO Format: %lld & %llu Submit Status uDebug ...

  3. UVALive - 3942 Remember the Word[树状数组]

    UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...

  4. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  5. POJ 3041 Asteroids

     最小点覆盖数==最大匹配数 Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12678 Accepted:  ...

  6. Asteroids(匈牙利算法入门)

    Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16211   Accepted: 8819 Descri ...

  7. hdu 1240:Asteroids!(三维BFS搜索)

    Asteroids! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  8. 思维 UVALive 3708 Graveyard

    题目传送门 /* 题意:本来有n个雕塑,等间距的分布在圆周上,现在多了m个雕塑,问一共要移动多少距离: 思维题:认为一个雕塑不动,视为坐标0,其他点向最近的点移动,四舍五入判断,比例最后乘会10000 ...

  9. UVALive 6145 Version Controlled IDE(可持久化treap、rope)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

随机推荐

  1. Hibernate 缓存机制二(转)

    感谢:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html 一.why(为什么要用Hibernate缓存?) Hibernate是一个 ...

  2. VB将PDF流写入ACCESS数据库,通过AcroPDF控件读出PDF流之实现

    问题描述: 1.把pdf文件写入access2.读出时用AcroPDF控件 问题解答: 使用流对象保存和显示图片与文件打开vb6,新建工程. 添加两个按钮,一个image控件注意:Access中的ph ...

  3. uva 10034

    计算所有点之间的权值   然后就是最小生成树 #include<cstring> #include<string> #include<cstdio> #includ ...

  4. Mesh Baker的基本操作与功能演示

    原地址:http://www.narkii.com/club/thread-301789-1.html 如何降低游戏在系统中的消耗并带给用户最佳的体验是开发者一直追求的目标,在Unity里面对于模型与 ...

  5. POJ2187Beauty Contest

    http://poj.org/problem?id=2187 题意 :有一个农场有N个房子,问最远的房子相距多少距离 . 思路 :凸包,旋转卡壳,通过寻找所有的对锺点,找出最远的点对. #includ ...

  6. 【mysql的编程专题⑥】视图

    视图是表的一个映射,是一张虚表,在结构上视图和普通的表没什么区别,一样可以用sql语句来增删改查; 视图创建后是一直存在数据库内 操作 创建视图 语法 CREATE [ALGORITHM]={UNDE ...

  7. ANDROID_MARS学习笔记_S01_007Linear_layout嵌套与layout_weight的设置

    一.介绍 二.1.linear_layout.xml <?xml version="1.0" encoding="utf-8"?> <Line ...

  8. R语言学习笔记:取数据子集

    上文介绍了,如何生成序列,本文介绍一下如何取出其数据子集 取出元素的逻辑值 > x<-c(0,-3,4,-1,45,90,5) > x>0 [1] FALSE FALSE  T ...

  9. python学习笔记一--字符串

    一.字符串: (一)字符串里单个元素的操作 1. 单个字符(元素)的序列组合. 2. 序列:单个字符的位置 3. 序列的操作:内置函数len获取长度,加位置索引 4. 获取字符串的里的元素:正向索引+ ...

  10. Android开发之注解式框架ButterKnife的使用

    ButterKnife官网 其实ButterKnife的注解式,与xUtils的ViewUtils模块基本上差不多,只要用过xUtils,这个框架基本上就会了. 一.原理. 最近发现一个很好用的开源框 ...