hdoj 3756 Dome of Circus(三分)

来源:互联网 发布:abaqus软件价格 编辑:程序博客网 时间:2024/04/30 22:08

【题目大意】:给出一堆三维的点,求一个最小的圆锥覆盖所有的点。


【解题思路】:这道题上一次做是暑假之后的一次组队赛的题目。其实自从某一次yy到三分极值这种方法之后,顿悟。队友说,一切三分均可秒。

哎...我自惭形秽啊...

首先,圆锥任何一个沿高的截面的形状都是一样的,所以对于每一个点都会在某一个截面上,而截面均相同。

这样,我们完成了首步,某种程度上类似于降维的思想。其次,我们发现截面的一半都是一个直角三角形。

在最小圆锥的这种情况下,必定有至少一个点位于截面三角形的斜边上,而这个点,势必是最外层的点。根据相似三角形的定义,我们可以由直径推出高,或由高推出直径,而且半径越长,高越短,反亦然。

因此,这显然不是一个单调的问题,故而考虑三分极值,因为必定存在一个半径和高满足体积最小这一条件。


【代码】:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip>                   using namespace std;                   #define eps 1e-8#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long longstruct Point{      double x, y, z, rr;      Point() {}      Point(double a, double b, double c){          x = a, y = b, z = c, rr = sqrt(x * x + y * y);      }  }point[20000];  double maxr,ansr,ansh,ansh1;  int n;  double check(double r){      double maxx=-1.0;      for (int i=0; i<n; i++){          double z=point[i].z,rr=point[i].rr;          double k=point[i].z/(r-point[i].rr);          if (maxx<k) {maxx=k;}      }      return maxx*r;  }int main() {    int T;      scanf("%d",&T);      while (T--) {          scanf("%d", &n);          maxr=0.0;          double x, y, z;          for (int i=0; i<n; i++){              scanf("%lf%lf%lf",&x,&y,&z);              point[i]=Point(x, y, z);              if (point[i].rr>maxr) maxr=point[i].rr;          }          double low=maxr,high=11000,mid,mmid;          while (low+eps<high)          {              mid=(low+high)/2.0;              mmid=(mid+high)/2.0;              double k1,k2;              k1=check(mid);              k2=check(mmid);              if (k1*mid*mid<k2*mmid*mmid) {                  high=mmid;                  ansr=mid;                  ansh=k1;              } else {                  low=mid;                  ansr=mmid;                  ansh=k2;              }          }          printf("%.3f %.3f\n", ansh, ansr);      }          return 0;}


原创粉丝点击