杭电 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);
    }
}

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

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

posted @ 2013-02-15 22:41  SF-_-  阅读(197)  评论(0编辑  收藏  举报