zoukankan      html  css  js  c++  java
  • uvalive 4589 Asteroids

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

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

    三维凸包+重心求法

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

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<queue>
      6 using namespace std;
      7 
      8 const double eps = 1e-8;
      9 int dcmp(double x)
     10 {
     11     if(fabs(x) < eps) return 0;
     12     else return x < 0 ? -1 : 1;
     13 }
     14 
     15 struct Point3
     16 {
     17     double x, y, z;
     18     Point3(double x=0, double y=0, double z=0):x(x),y(y),z(z) { }
     19 };
     20 
     21 typedef Point3 Vector3;
     22 
     23 Vector3 operator + (const Vector3& A, const Vector3& B)
     24 {
     25     return Vector3(A.x+B.x, A.y+B.y, A.z+B.z);
     26 }
     27 Vector3 operator - (const Point3& A, const Point3& B)
     28 {
     29     return Vector3(A.x-B.x, A.y-B.y, A.z-B.z);
     30 }
     31 Vector3 operator * (const Vector3& A, double p)
     32 {
     33     return Vector3(A.x*p, A.y*p, A.z*p);
     34 }
     35 Vector3 operator / (const Vector3& A, double p)
     36 {
     37     return Vector3(A.x/p, A.y/p, A.z/p);
     38 }
     39 
     40 bool operator == (const Point3& a, const Point3& b)
     41 {
     42     return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0 && dcmp(a.z-b.z) == 0;
     43 }
     44 
     45 Point3 read_point3()
     46 {
     47     Point3 p;
     48     scanf("%lf%lf%lf", &p.x, &p.y, &p.z);
     49     return p;
     50 }
     51 
     52 double Dot(const Vector3& A, const Vector3& B)
     53 {
     54     return A.x*B.x + A.y*B.y + A.z*B.z;
     55 }
     56 double Length(const Vector3& A)
     57 {
     58     return sqrt(Dot(A, A));
     59 }
     60 double Angle(const Vector3& A, const Vector3& B)
     61 {
     62     return acos(Dot(A, B) / Length(A) / Length(B));
     63 }
     64 Vector3 Cross(const Vector3& A, const Vector3& B)
     65 {
     66     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);
     67 }
     68 double Area2(const Point3& A, const Point3& B, const Point3& C)
     69 {
     70     return Length(Cross(B-A, C-A));
     71 }
     72 double Volume6(const Point3& A, const Point3& B, const Point3& C, const Point3& D)
     73 {
     74     return Dot(D-A, Cross(B-A, C-A));
     75 }
     76 Point3 Centroid(const Point3& A, const Point3& B, const Point3& C, const Point3& D)
     77 {
     78     return (A + B + C + D)/4.0;
     79 }
     80 
     81 double rand01()
     82 {
     83     return rand() / (double)RAND_MAX;
     84 }
     85 double randeps()
     86 {
     87     return (rand01() - 0.5) * eps;
     88 }
     89 
     90 Point3 add_noise(const Point3& p)
     91 {
     92     return Point3(p.x + randeps(), p.y + randeps(), p.z + randeps());
     93 }
     94 
     95 struct Face
     96 {
     97     int v[3];
     98     Face(int a, int b, int c)
     99     {
    100         v[0] = a;
    101         v[1] = b;
    102         v[2] = c;
    103     }
    104     Vector3 Normal(const vector<Point3>& P) const
    105     {
    106         return Cross(P[v[1]]-P[v[0]], P[v[2]]-P[v[0]]);
    107     }
    108     // f是否能看见P[i]
    109     int CanSee(const vector<Point3>& P, int i) const
    110     {
    111         return Dot(P[i]-P[v[0]], Normal(P)) > 0;
    112     }
    113 };
    114 
    115 // 增量法求三维凸包
    116 // 注意:没有考虑各种特殊情况(如四点共面)。实践中,请在调用前对输入点进行微小扰动
    117 vector<Face> CH3D(const vector<Point3>& P)
    118 {
    119     int n = P.size();
    120     vector<vector<int> > vis(n);
    121     for(int i = 0; i < n; i++) vis[i].resize(n);
    122 
    123     vector<Face> cur;
    124     cur.push_back(Face(0, 1, 2)); // 由于已经进行扰动,前三个点不共线
    125     cur.push_back(Face(2, 1, 0));
    126     for(int i = 3; i < n; i++)
    127     {
    128         vector<Face> next;
    129         // 计算每条边的“左面”的可见性
    130         for(int j = 0; j < cur.size(); j++)
    131         {
    132             Face& f = cur[j];
    133             int res = f.CanSee(P, i);
    134             if(!res) next.push_back(f);
    135             for(int k = 0; k < 3; k++) vis[f.v[k]][f.v[(k+1)%3]] = res;
    136         }
    137         for(int j = 0; j < cur.size(); j++)
    138             for(int k = 0; k < 3; k++)
    139             {
    140                 int a = cur[j].v[k], b = cur[j].v[(k+1)%3];
    141                 if(vis[a][b] != vis[b][a] && vis[a][b]) // (a,b)是分界线,左边对P[i]可见
    142                     next.push_back(Face(a, b, i));
    143             }
    144         cur = next;
    145     }
    146     return cur;
    147 }
    148 
    149 struct ConvexPolyhedron
    150 {
    151     int n;
    152     vector<Point3> P, P2;
    153     vector<Face> faces;
    154 
    155     bool read()
    156     {
    157         if(scanf("%d", &n) != 1) return false;
    158         P.resize(n);
    159         P2.resize(n);
    160         for(int i = 0; i < n; i++)
    161         {
    162             P[i] = read_point3();
    163             P2[i] = add_noise(P[i]);
    164         }
    165         faces = CH3D(P2);
    166         return true;
    167     }
    168 
    169     Point3 centroid()
    170     {
    171         Point3 C = P[0];
    172         double totv = 0;
    173         Point3 tot(0,0,0);
    174         for(int i = 0; i < faces.size(); i++)
    175         {
    176             Point3 p1 = P[faces[i].v[0]], p2 = P[faces[i].v[1]], p3 = P[faces[i].v[2]];
    177             double v = -Volume6(p1, p2, p3, C);
    178             totv += v;
    179             tot = tot + Centroid(p1, p2, p3, C)*v;
    180         }
    181         return tot / totv;
    182     }
    183 
    184     double mindist(Point3 C)
    185     {
    186         double ans = 1e30;
    187         for(int i = 0; i < faces.size(); i++)
    188         {
    189             Point3 p1 = P[faces[i].v[0]], p2 = P[faces[i].v[1]], p3 = P[faces[i].v[2]];
    190             ans = min(ans, fabs(-Volume6(p1, p2, p3, C) / Area2(p1, p2, p3)));
    191         }
    192         return ans;
    193     }
    194 };
    195 
    196 int main()
    197 {
    198     int n, m;
    199     ConvexPolyhedron P1, P2;
    200     while(P1.read() && P2.read())
    201     {
    202         Point3 C1 = P1.centroid();
    203         double d1 = P1.mindist(C1);
    204         Point3 C2 = P2.centroid();
    205         double d2 = P2.mindist(C2);
    206         printf("%.8lf
    ", d1+d2);
    207     }
    208     return 0;
    209 }
    View Code
  • 相关阅读:
    Linux 安装jdk 报错 Error: could not find libjava.so Error: Could not find Java SE Runtime Environment.
    k8s 挂载ceph rbd
    spinnaker结合表达式实现发版时下拉列表选择docker image
    istio环境集成zipkin
    istio 日志打印 request body 和respon body
    jenkins任务中无法执行sudo,管理员操作
    ansible根据shell命令返回值,判断是否应该急继续往下执行
    ReplicaSetController、ReplicationController
    kubeproxy
    PodGCController
  • 原文地址:https://www.cnblogs.com/ITUPC/p/4903267.html
Copyright © 2011-2022 走看看