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

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

三维凸包+重心求法

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

 #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. 30分钟让你了解MongoDB基本操作

    今天记录下MongoDB的基本操作,这只是最基本的,所以是应该掌握的. 数据库 数据库是一个物理容器集合.每个数据库都有自己的一套文件系统上的文件.一个单一的MongoDB服务器通常有多个数据库. 集 ...

  2. 【数学/扩展欧几里得/Lucas定理】BZOJ 1951 :[Sdoi 2010]古代猪文

    Description “在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……” ——选自猪王国民歌 很久很久以前,在山的那边 ...

  3. [转载]HTML5 Audio/Video 标签,属性,方法,事件汇总

    <audio> 标签属性: src:音乐的URL preload:预加载 autoplay:自动播放 loop:循环播放 controls:浏览器自带的控制条 <audio id=& ...

  4. The7th Zhejiang Provincial Collegiate Programming Contest->Problem A:A - Who is Older?

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3322 可以看样例猜题意的水题. #include<bits/stdc ...

  5. Injection Attacks-Log 注入

    日志注入(也称日志文件注入) 很多应用都维护着一系列面向授权用户.通过 HTML 界面展示的日志,因而成为了攻击者的首要目标,这些攻击者试图伪装其他攻击.误导日志读者,甚至对阅读和分析日志监测应用的用 ...

  6. 修改jmeter jvm参数

    记录下常用的linux下 jmeter jvm参数修改,打开jmeter安装目录/bin/jmeter(非jmeter.sh) 1. 修改默认堆内存大小 #默认的 HEAP="-Xms512 ...

  7. HDU4908——BestCoder Sequence(BestCoder Round #3)

    BestCoder Sequence Problem DescriptionMr Potato is a coder.Mr Potato is the BestCoder.One night, an ...

  8. Oracle Exception 处理

    1.问题来源Oracle中可以用dbms_output.put_line来打印提示信息,但是很容易缓冲区就溢出了.可以用DBMS_OUTPUT.ENABLE(1000000);来设置缓冲区的大小.但是 ...

  9. allegro飞线隐藏

    这些都是最基本的操作,你说的应该是飞线的显示和隐藏,命令在display下面,display>show rats>net(component/all) display>blank r ...

  10. 细说javascript 中的 window.open() 参数设置

    今天遇到一个问题,就是要用javascript中的window.open()打开一个新的网页,而且新打开的网页要在原来网页的基础之上,在查了一些资料之后,找到里一下方法:(其中,url 为链接的地址) ...