我所理解的三分很简单,就是求极小值极大值。思想和二分差不多。板子如下。
double solve(double x)
{
// 计算函数值,即f(x)
}
double sanfen(double left, double right)
{
// 三分搜索,找到最优解(求函数最大值下的自变量值)
double midl, midr;
while (right-left > 1e-7)
{
midl = (left + right) / 2;
midr = (midl + right) / 2;
// 如果是求最小值的话这里判<=即可
if(solve(midl) >= solve(midr)) right = midr;
else left = midl;
}
return left;
}
通过一道简单例题来深入理解下三分。
题目:
开始每个人都在一条数轴上的某个位置上,位置大于等于1,都是整数,每个人有个最大移动速度,在数轴上某个点集合,可以花费最短的时间,求出这个最短的时间。
分析:
当找的这个点在最左边的时候,需要的时间最大,同理在最右边也是。越靠近中间,所需要的时间越小。刚好有个极小值点最小。所以就是一道典型的三分。
代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
const double eps=0.000001;
const int maxn=60010;
double a[maxn],b[maxn];
int n;
double check(double x)
{
double ans=0;
for(int i=0;i<n;i++)
ans=max(ans,fabs(x-a[i])/b[i]);
return ans;
}
int main()
{
double mmin=1.0*INF,mmax=-1.0*INF;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf",&a[i]);
mmin=min(mmin,a[i]);
mmax=max(mmax,a[i]);
}
for(int i=0;i<n;i++)
scanf("%lf",&b[i]);
double l=mmin,r=mmax;
while(l+eps<r)
{
double mid=(l+r)/2;
double mmid=(mid+r)/2;
if(check(mid)>check(mmid))l=mid;
else r=mmid;
}
printf("%.12lf\n",check(r));
return 0;
}