在单调函数中,我们经常用二分法来快速搜索可行解。在单峰函数中,我们则要用三分法来搜索函数的极值。
一般来说,三分法可以平均分,也可以第一个点分在左右端点的中点,第二个点分在中点和右端点的中点。(即在1/2和3/4处取两个点做三分)。
题目描述
给定抛物的高度和速度,求其最远的抛出距离,g取9.8 结果保留2位小数
样例输入
2
0 1 //0是高度 1是初始速度
1 2 //1是高度 2是初始速度
样例输出
0.10 //斜45°可以抛出最远距离
0.99
题目分析
这是一道高中物理题。公式推导不再说明,这题重点看三分法。
直接放代码。
#include <cstdio> // 为了防止世界被破坏 //
#include <iostream> // 为了守护世界和平 //
#include <cstring> // 贯彻爱与真实的邪恶 //
#include <string> // 可爱又迷人的反派角色 //
#include <sstream> // 田神! 卜神! //
#include <cmath> // 他们是穿梭在活动室的火箭队 //
#include <cctype> // 美好的明天在等待着他们 //
#include <stack>//栈 // 喵~ //
#include <queue>//队列
#include <set>//集合
#include <map>//映射
#include <vector>//不定长数组
#include <algorithm>
using namespace std;
#define ll long long
#define INF 100000000
const double pi = 4*atan(1.0);
int gcd(int a,int b) {return b == 0? a:gcd(b,a%b);}
int lcm(int a,int b) {return a/gcd(a,b)*b;}
int h,v0;
double f(double t)//求角度为t时抛出的距离(物理公式推导)
{
return (v0*cos(t)/9.8)*(v0*sin(t)+sqrt(v0*v0*sin(t)*sin(t)+2*9.8*h));
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&h,&v0);
double l = 0,r = 90;
double ans = 0;//ans存放最大值
while(r-l >= 1e-6){//当r>=l
double mid = (l+r)/2.0;
double midmid = (mid+r)/2.0;
if(f(mid) > f(midmid)){
if(f(mid) > ans) ans = f(mid);
r = midmid;
}else{
if(f(midmid) > ans) ans = f(midmid);
l = mid;
}
}
printf("%.2f\n",ans);
}
return 0;
}
PS:关于三分法可以从图像上来直观理解。