zoukankan      html  css  js  c++  java
  • POJ2069 最小球覆盖 几何法和退火法

    对这种问题不熟悉的读者 可以先去看一看最小圆覆盖的问题 ZOJ1450

    现在我们来看最小球覆盖问题POJ2069 题目很裸,给30个点 求能覆盖所有点的最小球的半径。

    先给出以下几个事实:

    1.对于一个点,球心就是这个点且半径无穷小。

    2.对于两个点,球心是两个点线段的中点,半径就是线段长度的一半。

    3.对于三个点,三个点构成的平面必为球的大圆,所以球心是三角形的外心,半径就是球心到某个点的距离。

    4.对于四个点,若四个点共面则转化到3,只需考虑某三个点的情况,若四点不共面,四面体可以唯一确定一个外接球。

    5.对于五个及以上点,其最小球必为其中某4个点的外接球(假设不全共面)。

    C(30,4)是可以接受的复杂度。在编程实现的时候,碰到不在球内的点,就让它成为球面上的点,期望复杂度为O(n)。

    -----------------------------------------------------------------------------------------------------------------------------------------------

    以上我们给出了一般的几何解法,但是求三角形外心和四面体的外界球,方程很复杂,代码量也很大,有没有简单的方法呢?

    我们根据以上5个事实,可以知道所谓最小球的球心,它必然处于一个稳定态,也就是与它距离最远的点最多有4个且等距离。

    于是,我们首先任选一个点作为球心,并找到点集中与它距离最远的点,我们让球心靠近最远的点,不断重复此过程,就可以让球心达到稳定态了!此时我们就找到了最小球。

     1 #include <iostream>  
     2 #include<cstdio>  
     3 #include<algorithm>  
     4 #include<cstring>  
     5 #include<cmath>  
     6 using namespace std;  
     7 const double eps=1e-7;  
     8 struct point3D  
     9 {  
    10     double x,y,z;  
    11 } data[35];  
    12 int n;  
    13 double dis(point3D a,point3D b)  
    14 {  
    15     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));  
    16 }  
    17 double solve()  
    18 {  
    19     double step=100,ans=1e30,mt;  
    20     point3D z;  
    21     z.x=z.y=z.z=0;  
    22     int s=0;  
    23     while(step>eps)  
    24     {  
    25         for(int i=0; i<n; i++)  
    26             if(dis(z,data[s])<dis(z,data[i])) s=i;  
    27         mt=dis(z,data[s]);  
    28         ans=min(ans,mt);  
    29         z.x+=(data[s].x-z.x)/mt*step;  
    30         z.y+=(data[s].y-z.y)/mt*step;  
    31         z.z+=(data[s].z-z.z)/mt*step;  
    32         step*=0.98;  
    33     }  
    34     return ans;  
    35 }  
    36 int main()  
    37 { // freopen("t.txt","r",stdin);
    38     double ans;  
    39     while(~scanf("%d",&n),n)  
    40     {  
    41         for(int i=0; i<n; i++)  
    42             scanf("%lf%lf%lf",&data[i].x,&data[i].y,&data[i].z);  
    43         ans=solve();  
    44         printf("%.5f
    ",ans);  
    45     }  
    46     return 0;  
    47 }  
    View Code

     

  • 相关阅读:
    CQUOJ 10819 MUH and House of Cards
    CQUOJ 9920 Ladder
    CQUOJ 9906 Little Girl and Maximum XOR
    CQUOJ 10672 Kolya and Tandem Repeat
    CQUOJ 9711 Primes on Interval
    指针试水
    Another test
    Test
    二分图匹配的重要概念以及匈牙利算法
    二分图最大匹配
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6827790.html
Copyright © 2011-2022 走看看