杭电 3756 Dome of Circus 解题报告

    将所有的点转化为x-z平面上,求使所有的点在直线x/r+z/h=1的下方,且使r*r*h最小的h与r的值。

    依然使用三分法。可以这么多点,如何处理呢?

    笔者首先选取x坐标最大的点,使直线过此点,逆时针旋转至下一个点,三分求体积最小值。再使以下一点逆时针旋转,直至没有点或者直线斜率k>=0。这样每次所有的点都在直线下方。AC代码如下:

#include<iostream>

#include<cmath>

using namespace std;



double pi=acos(-1.0);

double eps=1e-9;



double fun(double x,double y,double q)

{

    double r,h;

    r=x+y*tan(q*pi);

    h=x/tan(q*pi)+y;

    return r*r*h;

}



double threeSplit(double x,double y,double a,double b)

{

    double mida,midb;

    while(b-a>eps)

    {

        mida=(a+a+b)/3;

        midb=(a+b+b)/3;

        if(fun(x,y,mida)<fun(x,y,midb))

            b=midb;

        else

            a=mida;

    }

    return a;

}



struct Point

{

    double x,y;

} p[10001];



int main()

{

    int cas,i,n,max_p,current_p,next_p;

    double q,max_q,v,max_v,k,max_k,max_x,a,b;

    cin>>cas;

    while(cas--)

    {

        cin>>n;

        max_x=-1;

        current_p=0;

        for(i=1;i<=n;i++)

        {

            cin>>a>>b>>p[i].y;

            p[i].x=sqrt(a*a+b*b);

            if(max_x<p[i].x)

            {

                max_x=p[i].x;

                current_p=i;

            }

            else if(max_x==p[i].x && p[i].y>p[current_p].y)

                current_p=i;

        }



        max_v=a=b=eps;

        while(1)

        {

            next_p=-1;

            max_k=0;

            for(i=1;i<=n;i++)

                if(i!=current_p)

                    if(p[i].y-p[current_p].y>0 && max_k<(k=(p[i].y-p[current_p].y)/(p[current_p].x-p[i].x)))

                    {

                        max_k=k;

                        next_p=i;

                    }

            if(next_p==-1||max_k<=0)

                b=0.5-eps;

            else

                b=atan(1/max_k)/pi;



            q=threeSplit(p[current_p].x,p[current_p].y,a,b);

            if(max_v<(v=fun(p[current_p].x,p[current_p].y,q)))

            {

                max_v=v;

                max_q=q;

                max_p=current_p;

            }



            if(next_p==-1||max_k<=0)

                break;

            current_p=next_p;

            a=b;

        }

        printf("%.3f %.3f\n",p[max_p].x/tan(max_q*pi)+p[max_p].y+eps,p[max_p].x+p[max_p].y*tan(max_q*pi)+eps);

    }

}

    笔者已经不想改这个代码了。。。希望你可以看懂

    网上还搜到一份不一样的代码,思路不太一样,笔者没有认真去看。因为这题也花了不少时间,懒得去弄了。。。

你可能感兴趣的:(dom)