题意如下:
有一个高H的灯,在灯的右边D距离有一堵墙,在灯和墙之间有一个高h人,h小于H。问人的影子最多有多长。如下图求L
高中物理题,相信学霸可以用公式退出来,不过也会挺费事。我们用三分查找可以轻松求解。
首先我们要证明影子随着人向右走,是一个先增后减的单峰函数。 这个是常识 0.0 。大致推理一下,如果没有墙 ,影子是越来越长的,有了墙,使得本该极长的影子,有了上限人的高度。 可能服从单峰函数,当然不一定是真的,然后我们写出求影长的公式 f(x) ,一不小心发现确实是单峰函数,然后果断三分查找啊,
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
const double esp=0.00000001;
double H,h,d;
//这里是f(x) 一个单峰函数 凸的,
double f(double x){
// H/h=(x+a)/a;相似三角形
double a= (h*x)/(H-h);//如果没有墙时的影长
if(a>d-x){//如果墙上有影子
double b= (a-(d-x))/a*h;//墙上影子的长度
a=a-(a-(d-x))+b;//影子的总长度
}
return a;
}
//这里是三分的内容
double oneThird(double l,double r){
while(r-l>esp){
double mid=l+(r-l)/2;
double mmid=mid+(r-mid)/2;
if(f(mid)>f(mmid)){
r=mmid;
}
else l=mid;
}
return l;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%lf%lf%lf",&H,&h,&d);
printf("%.3lf\n",f( oneThird(0.01,d) ) );
}
return 0;
}
挺简单的对吧
里面有个很蛋疼的地方,三分区间不能从零开始,我 wrong 了好几次就是因为0。感觉可能是f(x)的一些原因,但谁知道呢