Light Bulb ZOJ - 3203 三分
三分:
和二分非常类似的一个算法,与二分不同的是
二分是单调的,而三分是一个先增后减或者先减后增
三分可以求出峰值。
注意三分一定是严格单调的,不能有相等的情况。
讲个例题:
题意:
一个人发现他的影子的长度随着他在灯泡和墙壁之间走到时发生着变化。一个突然的想法出现在脑海里,他想知道他的影子的最大长度。
例图:
输入格式
输入文件的第一行包含一个整数 ,表示测试数据的组数。
对于每组测试数据,仅一行,包含三个实数 , 和 , 表示灯泡的高度, 表示 mildleopard 的身高, 表示灯泡和墙的水平距离。
输出格式
输出文件共 行,每组数据占一行表示影子的最大长度,保留三位小数。
样例
样例输入
3
2 1 0.5
2 0.5 3
4 3 4
样例输出
1.000
0.750
4.000
题解:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<iostream> 4 #include<string.h> 5 #include<algorithm> 6 using namespace std; 7 const int maxn=500005; 8 const int INF=0x3f3f3f3f; 9 const int eps=1e-11; 10 typedef long long ll; 11 double height,high,width; 12 double panduan(double x) 13 { 14 double ans=high/height*width; 15 double dis=width-x; //dis就是人距离墙的距离 16 if(ans-dis>0) //ans就是影子不在墙的上面时它的长度 17 { 18 double z=dis/width; 19 double sum=dis+(z*height-high)/(z-1.0); 20 return sum; 21 } 22 else 23 { 24 return ans; 25 } 26 } 27 int main() 28 { 29 int t; 30 scanf("%d",&t); 31 while(t--) 32 { 33 scanf("%lf%lf%lf",&height,&high,&width); 34 double l=0,r=width; //我的三分是三分的人距离墙的距离 35 while(r - l > 1e-11) //这就是三分模板了,只要确定了三分的上界和下界就可以直接代入使用 36 { 37 double m1 = l + (r - l) / 3; 38 double m2 = r - (r - l) / 3; 39 if(panduan(m1) > panduan(m2)) r = m2; 40 else l = m1; 41 } 42 printf("%.3lf\n", panduan(l)); 43 } 44 return 0; 45 }