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

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

三维凸包+重心求法

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

 #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. JAVA CAS单点登录(SSO) 教程

    一.教程前言 教程目的:从头到尾细细道来单点登录服务器及客户端应用的每个步骤 单点登录(SSO):请看百科解释猛击这里打开 本教程使用的SSO服务器是Yelu大学研发的CAS(Central Auth ...

  2. BZOJ 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果

    Description 每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N(1≤N≤100000)个牛棚里转悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大, ...

  3. ThinkPHP下隐藏index.php以及URL伪静态

    第一种方法: 设置url的重写模式(默认模式是1) 'URL_MODEL' => 2, // URL访问模式,可选参数0.1.2.3,代表以下四种模式: 第二种方法:  使用Apache来进行设 ...

  4. Java经典书籍

    Java Web开发教程---孙霞JSP应用开发详解(第三版)---刘晓华.张健.周慧贞Spring in Action---Craig Walls精通Struts基于MVC的Java Web设计与开 ...

  5. 配置SQL Server 2008服务器

    怎么配置SQL Server 2008服务器_百度经验 http://jingyan.baidu.com/article/9faa7231a922c1473c28cb23.html 1.验证安装是否成 ...

  6. 218. The Skyline Problem

    题目: A city's skyline is the outer contour of the silhouette formed by all the buildings in that city ...

  7. forks rate异常

    一.收到nagios Current_load报警短信

  8. C#中string.Format()和ToString()格式化方法

    C#数字格式化输出是我们在编程中经常需要处理的事情,那么这里向你介绍了一些C#数字格式化输出的例子,这样就会方便你来选择和比较,什么方式是比较适合自己项目的. int a = 12345678; C# ...

  9. System.Drawing.Graphics中比较重要的几个方法

    方法 常见参数 绘制的图形 DrawLine 钢笔.起点和终点 一段直线 DrawRectangle 钢笔.位置和大小 空心矩形 DrawEllipse 钢笔.位置和大小 空心椭圆 FillRecta ...

  10. [转] android自动化测试之MonkeyRunner使用实例(三)

    一.使用CMD命令打开模拟器 运行monkeyrunner之前必须先运行相应的模拟器或连上设备,不然monkeyrunner无法连接设备. 1.1  用Elipse打开Android模拟器或在CMD中 ...