Zoj 3203 Light Bulb

本题练习三分法,亦可用求导来求极值。

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3366

二分法适合解决单调性一致的问题,而如果单调性不一致,就要是要哪个三分法。

当需要求某凸性或凹形函数的极值,通过函数本身表达式并不容易求解时,就可以用三分法不断逼近求解。

基本模型:


对于本题而言

很容易发现当灯,人的头部和墙角成一条直线时(假设此时人站在A点),此时的长度是影子全在地上的最长长度。当人再向右走时,影子开始投影到墙上,当人贴着墙,影子长度即为人的高度。所以当人从A点走到墙,函数是先递增再递减,为凸性函数,所以我们可以用三分法来求解。

我们假设:人距离灯的水平距离为x,则不难推出:随着x的变化,L = D - x + H - D * (H - h) / x; 是先增后减函数。

我们立足于求其最大值。

x的初始值我们可以假设为:D - D*h/H,因为从0开始到此,L肯定是递增的,所以不必考虑先前的。

x最大值为D:

对于精确度而言,使用1e-10,1e-8 A不掉。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;

int t;
double H,h,D;

double cal(double x)
{
    return D - x + H - D * (H - h)/x;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif

    double l,r;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf %lf %lf",&H,&h,&D);
        l = D - D*h/H;
        r = D;
        while(l+1e-10<r)
        {
            double mid = (l + r)/2;
            double midmid = (mid + r)/2;
            if(cal(mid) - cal(midmid)<0)
            {
                l = mid;
            }
            else
            {
                r = midmid;
            }

        }
        printf("%.3lf\n",cal(l));
    }


    return 0;
}





你可能感兴趣的:(Zoj 3203 Light Bulb)