1. 程式人生 > >HDU 3756 還是三分

HDU 3756 還是三分

這題雖然是三維空間,但完全可以轉換到一個平面XZ考慮,Z軸不變,X軸是 根號下X*X+Y*Y

問題等價於求最小的三角形覆蓋平面上所有的點,必然至少有一點在斜邊上

設斜邊的斜率為K,一點為(a,b)

則斜邊方程為 y=k*(x-a)+b;

h=-a*k+b;

r=-b/k+a;

得到體積的方程,並證明是是凸性,有最小值

這時候我們就可以通過三分列舉一個變數,計算得到一個最小的另一個變數

假設H已知, 則R=a*h/(b-h) 最終求得答案

#include<math.h>
#include<string.h>
#include<stdio.h>
#define eps 1e-8
#define maxn 10010
struct point
{
   double x,z;
}p[maxn];
int n;
double maxx(double a,double b)
{
      return a>b?a:b;
} 
double getR(double h)
{
   double r=0.0;
   int i;
   for(i=0;i<n;i++)
      r=maxx(r,p[i].x*h/(h-p[i].z));
   return r;
}     
int main()
{
      while( scanf("%d",&n)==1)
      {
       double x,y,z;
       double h0=0.0;
       int i,j;
       for(i=0;i<n;i++)
       {
          scanf("%lf%lf%lf",&x,&y,&z);
          p[i].x=sqrt(x*x+y*y);
          p[i].z=z;
          h0=maxx(h0,p[i].z);
       }
       double l=h0+eps,r=1e6,mid,midmid;
       while(r-l>eps)
       {
          mid=(l+r)/2.0;
          midmid=(mid+r)/2.0;
          double r1=getR(mid);
          double r2=getR(midmid);
          if(r1*r1*mid<r2*r2*midmid)
          r=midmid;
          else
          l=mid;
       }
       printf("%.3lf %.3lf\n",l,getR(l));
    }
    return 0;
}