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

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

三维凸包+重心求法

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

 #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. AForm

    相信大部分程序员都接触过表单,表单是收集用户输入的不二之选,但是表单的开发又是最繁琐.最复杂的,简单地说,开发表单你需要涉及到很多知识: 布局,表单如何布局排版,看起来最清晰整洁,且符合用户体验 控件 ...

  2. 【LCA】bzoj 2144:跳跳棋

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 248  Solved: 121[Submit][Status][Discuss] ...

  3. <base target="_blank"/>

    <base target=_blank> 是将基本链接的目标框架都改为新页打开

  4. 关​于​h​i​b​e​r​n​a​t​e​中​双​向​外​键​关​联​o​n​e​-​t​o​-​o​n​e​的​p​r​o​p​e​r​t​y​-​r​e​f​=​的​问​题(转)

    大家都知道hibernate中的one-to-one映射主要有两种策略,(1)一对一主键关联(单向和双向).(2)一对一外键映射(单项和双向).本文主要讲解一下,一对一外键映射中的双向问题,在此前先通 ...

  5. socket选项自带的TCP异常断开检测

    TCP异常断开是指在突然断电,直接拔网线等等情况下,如果通信双方没有进行数据发送通信等处理的时候,无法获知连接已经断开的情况. 在通常的情况下,为了使得socket通信不受操作系统的限制,需要自己在应 ...

  6. define中的:#,##,#@

    [define中的:#,##,#@] #define Conn(x,y) x##y #define ToChar(x) #@x #define ToString(x) #x (2)x##y表示什么?表 ...

  7. http://blog.csdn.net/xyang81/article/details/7292380

    http://blog.csdn.net/xyang81/article/details/7292380

  8. [codility]Min-abs-sum

    https://codility.com/demo/take-sample-test/delta2011/ 0-1背包问题的应用.我自己一开始没想出来.“首先对数组做处理,负数转换成对应正数,零去掉, ...

  9. EPEL库安装

    EPEL是yum的一个软件源,里面包含了许多基本源里没有的软件了,但在我们在使用epel时是需要安装它才可以了.EPEL,即Extra Packages for Enterprise Linux的简称 ...

  10. poj2376

    最少区间覆盖问题: 首先我们想到将r排序,则以得出dp方程 f[i]=1 (l[i]=1) =min{f[j]}+1 (r[j]+1>=l[i]) 最后ans是min{f[j]} (r[j]&g ...