这个题一开始想用二分,想了想,二分只能用于单调递增和单调递减的函数,对于上凸和下凸函数,例如二次函数,所以要用三分,之前没有用过,学了一下,
三分查找通常用来迅速确定最值。
二分查找所面向的搜索序列的要求是:具有单调性(不一定严格单调);没有单调性的序列不是使用二分查找。
与二分查找不同的是,三分法所面向的搜索序列的要求是:序列为一个凸性函数。通俗来讲,就是该序列必须有一个最大值(或最小值),在最大值(最小值)的左侧序列,必须满足不严格单调递增(递减),右侧序列必须满足不严格单调递减(递增)。如下图,表示一个有最大值的凸性函数
1、mid与midmid在最值的同一侧。由于凸性函数在最大值(最小值)任意一侧都具有单调性,因此,mid与midmid中,更大(小)的那个 数自然更为靠近最值。此时,我们远离最值的那个区间不可能包含最值,因此可以舍弃。
2、mid与midmid在最值的两侧。由于最值在中间的一个区间,因此我们舍弃一个区间后,并不会影响到最值
void trichotomy(double L,double R)
{
double m1,m2;
while(L < R) //这里也可以直接跑for(int i = 0;i < 100;i++) 也能跑出来
{
m1 = L + (R - L) / 3;
m2 = R - (R - L) / 3;
if(f(m1) < f(m2))
{
R = m2 - 1e-6; //
}
{
L = m1 + 1e-6; // 这个精度需要自己把握,有一些题,就卡的1e-9
}
}
return (m1 + m2) / 2;
}
再说一下这个题吧,这个题,就是让你三分x,然后求一个最小值,
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <math.h>
#include <stack>
#include <utility>
#include <string>
#include <sstream>
#include <cstdlib>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10000 + 10;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int n;
int a[maxn],b[maxn],c[maxn];
double judge(double x)
{
double ans = -INF;
for(int i = 0;i < n;i++)
{
ans = max(ans,a[i]*x*x + b[i]*x + c[i]);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
double ans = 0;
for(int i = 0;i < n;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
double L = 0.0;double R = 1000.0;
double cur;
while(L < R)
{
double num1 = L + (R - L) / 3;
double num2 = R - (R - L) / 3;
if(judge(num1) < judge(num2))
{
R = num2 - 1e-9;
cur = judge(num2);
}
else
{
L = num1 + 1e-9;
cur = judge(num1);
}
}
printf("%.4lf\n",cur);
}
return 0;
}