[搜索算法]三分搜索初步

前言

对于单调函数,如果找到了其单调性,我们就可以使用二分的方法对其进行搜索。所以二分搜索的首要前提是具有单调性。当搜索的函数不具有单调性时,二分搜索就显得相形见绌了。所以对于较为复杂的函数,我们可以采用三分搜索和模拟退火的方法。这里主要来分析一下三分搜索算法。

前提

三分搜索适用于具有凹凸性的函数,如图所示为一个具有凸性质的函数(注意不一定为一个标准的二次函数,只需要在唯一极值两端的单调性不同即可)在这个函数中我们就可以使用三分搜索。
这里写图片描述

过程

(这一部分摘自三分查找-pi9nc的专栏,并略微进行修改。)

假设搜索最左端为 L ,最右端为R,这两个点的中点为 mid
三分搜索基于二分搜索,在右端点 R 与中点mid之间又开辟了一个新的搜索点 midmid ,通过这两个中间点的比较,来确定下一步的收缩情况。

1f(mid)>f(midmid)midmidmidmidmidf(mid)>f(midmid)midmid<mid

R=midmid

2f(mid)<f(midmid)midmidmidmidf(mid)<f(midmid)mid>midmid

L=mid

注意点
1、 mid midmid 在最值的同一侧。由于适用函数在最大值(最小值)任意一侧都具有单调性,因此, mid midmid 中,更大(小)的那个数自然更为靠近最值。此时,我们远离最值的那个区间不可能包含最值,因此可以舍弃。
2、 mid midmid 在最值的两侧。由于最值在中间的一个区间,因此我们舍弃一个区间后,并不会影响到最值。

举例1

The Moving Points
HDU - 4717
There are N points in total. Every point moves in certain direction and certain speed. We want to know at what time that the largest distance between any two points would be minimum. And also, we require you to calculate that minimum distance. We guarantee that no two points will move in exactly same speed and direction.
Input
The rst line has a number T(T<=10) , indicating the number of test cases.
For each test case, first line has a single number N(N<=300), which is the number of points.
For next N lines, each come with four integers Xi,Yi,VXi and VYi(106<=Xi,Yi<=106,102<=VXi,VYi<=102),(Xi,Yi) is the position of the i th point, and (VXi,VYi) is its speed with direction. That is to say, after 1 second, this point will move to (Xi+VXi,Yi+VYi).
Output
For test case X, output “Case #X: ” first, then output two numbers, rounded to 0.01, as the answer of time and distance.
Sample Input
2
2
0 0 1 0
2 0 -1 0
2
0 0 1 0
2 1 -1 0
Sample Output
Case #1: 1.00 0.00
Case #2: 1.00 1.00

这个题可以从中分析,这个函数的变化时不具有单调性的,所以用二分的方法肯定不行,但是进一步分析,我们可以得到,首先一定有一个且只有一个time点,当这个time点时,任意两点之间距离的最大值最小,且这个值的两端的单调性是相反的,都一定会大于这个time值时的结果,这个时候我们就可以用三分的方法去做。(证明过程可以用反证法,根据题意可以得到任意两点之间的距离一定是一个一次函数或者是一个开口向上的抛物线函数,假设有两个点使得结果最小,那么根据题意也就是有两个time点,所有函数都小于一个k值,根据单调性可以得到经过第一个time点后,不存在一个点,所有函数都小于这个time点的结果k值,读者可以自己证明。)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#define INF 0x7ffffff
#define eps 1e-6
using namespace std;

struct Node
{
    double x,y,vx,vy;
}nodes[330];

double GetDistance(Node a, Node b,double TIME){
    return sqrt(
    ((a.x+TIME*a.vx)-(b.x+TIME*b.vx))*
    ((a.x+TIME*a.vx)-(b.x+TIME*b.vx))+
    ((a.y+TIME*a.vy)-(b.y+TIME*b.vy))*
    ((a.y+TIME*a.vy)-(b.y+TIME*b.vy))
    );
}

int N;
double cal(double mid){
    double res =0;
    for(int i=0;i<N;i++){
        for(int j=i+1;j<N;j++){
            res = max(res,GetDistance(nodes[i],nodes[j],mid));
        }
    }
    return res;
}

int main()
{
    int TotalNumber,CasesNumber=1;
    cin>>TotalNumber;
    while(TotalNumber--)
    {
        double Time=0,Distance=0;
        cin>>N;
        for(int i=0;i<N;i++){scanf("%lf%lf%lf%lf",&nodes[i].x,&nodes[i].y,&nodes[i].vx,&nodes[i].vy);}
        double l = 0,r = INF;
        while((r-l)>eps){
            double mid1 = (r+l)/2;
            double mid2 = (r+mid1)/2;
            if(cal(mid1) >= cal(mid2)) l = mid1+eps;
            else r = mid2-eps;
        }
        Time = l,Distance = cal(l);
        printf("Case #%d: %.2f %.2f\n",CasesNumber++,Time,Distance);
    }
    return 0;
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值