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

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

三维凸包+重心求法

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

 #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. PLSQL显示乱码-无法进行中文条件查询解决

    PLSQL显示乱码-无法进行中文条件查询解决 原因: PLSQL乱码问题皆是ORACLE服务端字符集编码与PLSQL端字符集编码不一致引起.类似乱码问题都可以从编码是否一致上面去考虑. 解决: 1. ...

  2. API断点大全

    1.限制程序功能函数 EnableMenuItem 允许.禁止或变灰指定的菜单条目EnableWindow 允许或禁止鼠标和键盘控制指定窗口和条目(禁止时菜单变灰) 2.对话框函数 CreateDia ...

  3. Nagios Apache报Internal Server Error错误的解决方法

    今天配置Nagios的时候遇到了一些麻烦,前面的步骤都一切顺利,nagios运行后,可以看到nagios的主页,但点击左边的菜单时总是提示Internal Server Error错误.错误如下: v ...

  4. HDU4611+数学

    /* 找规律 题意:abs(i%A - i%B) 对i从0~N-1求和 从0~N-1一个一个算必TLE,着A,B两者差相同的部分合并起来算 */ #include<stdio.h> #in ...

  5. [itint5]完全二叉树节点个数的统计

    http://www.itint5.com/oj/#4 这题是利用完全二叉树的性质计算节点数目.那么是通过比较左右子树的最左结点的高度来看那边是满的,然后递归计算. //使用getLeftChildN ...

  6. POJ3083——Children of the Candy Corn(DFS+BFS)

    Children of the Candy Corn DescriptionThe cornfield maze is a popular Halloween treat. Visitors are ...

  7. Android如何在ListView中嵌套ListView

    前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个ListItem中放入另外一个ListView.但刚开始的时候,会发现放入的小ListVie ...

  8. 敏捷开发系列之旅 第二站(走近XP极限编程)

    http://blog.csdn.net/happylee6688/article/details/21551065 上篇文章,我们探讨了什么是敏捷开发,以及敏捷开发的方法学.在这篇文章中,我们将继续 ...

  9. puppet&mcollective客户端安装

    一.环境: 1.客户端:            fedora 19 2.DnsServer:     192.168.0.160 3.server1.xxx.com(10.8.1.201):运行以下服 ...

  10. VMware Workstation与Hyper-V不兼容。请先从系统中移除Hyper-V角色,然后再运行VMware Workstation。

    VMware Workstation与Hyper-V不兼容.请先从系统中移除Hyper-V角色,然后再运行VMware Workstation. 今天在用win8.1的时候发现了这个问题,解决办法如下 ...