hdu5017:补题系列之西安网络赛1011

补题系列之西安网络赛1011

题目大意:给定一个椭球: 求它到原点的最短距离.

思路:

对于一个椭球的标准方程 x^2/a^2 + y^2/b^2 +z^2/c^2=1 来说,它到原点的最短距离即为min(a,b,c)

所以我们需要把原方程化为标准型。

这时候线代就排上用场了,注意到原方程是一个二次型。

化为标准型 1/(k1)*x^2+1/(k2)*y^2+1/(k3)*z^2=1 后  min(k1,k2,k3)即为答案

而这里的1/k1,1/k2,1/k3 就是二次型矩阵的特征值

如何求特征值呢?

我们写出二次型矩阵

       |   a    f/2   e/2  |

T=   |   f/2   b    d/2  |

       |   e/2 d/2   c    |   由行列式| λE-T|=0 可以得到一个关于λ的一元三次方程,令 k=1/λ,

把它记为  a*k^3+b*k^2+c*k+d=0(注意这里的a,b,c,d都是关于原方程中a,b,c,d的多项式)

解这个一元三次方程,可以使用求根公式:盛金公式(其他方法我还不会)

 

 

 

 

分此四种情况讨论求解即可。。

代码:

#include <stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define MAXN 10000
const double p=sqrt(3.0);
const double inf=0.0000001;
double min(double a,double b,double c)
{
    return min(a,min(b,c));
}
int main()
{

    double aa,bb,cc,dd,ee,ff;
    double A,B,C,a,b,c,d;
    while(scanf("%lf%lf%lf%lf%lf%lf",&aa,&bb,&cc,&dd,&ee,&ff)!=EOF)
    {
        double ans;
        a=4*aa*bb*cc+dd*ee*ff-bb*ee*ee-aa*dd*dd-ff*ff*cc;
        b=4*aa*bb+4*bb*cc+4*aa*cc-ee*ee-ff*ff-dd*dd;
        c=4*aa+4*bb+4*cc;
        d=4.0;
        A=b*b-3*a*c;
        B=b*c-9*a*d;
        C=c*c-3*b*d;
        double q=B*B-4*A*C;
        if(fabs(A-B)<inf&&fabs(A)<inf)
        {
            printf("%.8lf\n",sqrt(fabs(-c/b)));
            continue;
        }
        if(fabs(B*B-4*A*C)<inf)
        {
            double k=B/A;
            ans=min(fabs(-b/a+k),fabs(-k/2));
            printf("%.8f\n",sqrt(ans));
            continue;
        }
        if(q>0)
        {
            double x=A*b+3*a*((-B+sqrt(q))/2);
            double y=A*b+3*a*((-B-sqrt(q))/2);
            double t1= x>0?pow(x,1.0/3):-(pow(fabs(x),1.0/3));
            double t2= y>0?pow(y,1.0/3):-(pow(fabs(y),1.0/3));
            ans=(-b-t1-t2)/(3*a);
            printf("%.8f\n",sqrt(fabs(ans)));
            continue;
        }
        double t=acos((2*A*b-3*a*B)/(2*sqrt(A*A*A)))/3;
        ans=min(fabs((-b-2*sqrt(A)*cos(t))/(3*a)),fabs(((-b)+sqrt(A)*(cos(t)+p*sin(t)))/(3*a)),fabs(((-b)+sqrt(A)*(cos(t)-p*sin(t)))/(3*a)));
        printf("%.8f\n",sqrt(ans));

    }

    return 0;
}

 

posted @ 2014-09-16 13:27  Lnever  阅读(163)  评论(0编辑  收藏  举报