二分 1436:数列分段II 1433:【例题1】愤怒的牛

二分

一、二分

       二分法,在一个单调有序的集合或函数中查找一个解,每次分为左右两部分,判断解在哪个部分中并调整上下界,直到找到目标元素,每次二分后都将舍弃一半的查找空间,因此效率很高

       例如,对于在实数区间[L,R]内递增的连续函数f(x),求[L,R]内f(x)的零点J。J称为(x)在[L,R]内的零点,当且仅当满足:

任意L≤x<J,f(x)<0

任意J<x≤R,f(x)>0

f(J)=0

       二分法的思想是不断将待求解区间平均分成两份,根据求解区间中点的情况来确定目标元素所在的区间,这样就把解的范围缩小了一半

       设当前求解区间为 [ l , r ] , 它的中点为mid =( l+r )/2则有

若f(m)<0,则J∈[m,r];

若f(m)>0,则J∈[l,m];

若f(m)=0,则J=m

       显然,二分算法的复杂度为O(二分次数×单次判定复杂度)

 

 

二、二分写法

1.整数定义域上的二分

【代码实现】

int Erfen(int l,int r)
{
    int l=1,r=n,ans;
    while(l<=r)
    {
        int mid=(l+r)/2;
        //int mid=l+(r-l)/2;
        if(check(mid))  //若满足要求,记下答案,缩小范围 
        {
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    return ans;
}

2.实数定义域上的二分

【代码实现】

int Erfen(double l,double r)
{
    double eps=0.001; //根据题目
    while(fabs(r-l)>eps)
    {
        double mid=(l+r)/2.0;
        if(check(mid))    r=mid;
        else l=mid;
    }
    return l;
}

注意:eps设定要根据题目来,有时候太小,会陷入死循环

三、二分法常见模型

1.二分答案
       最小值最大(或是最大值最小)问题,这类双最值问题常常选用二分法求解,也就是确定答案后,配合贪心、DP等其他算法检验这个答案是否合理,将最优化问题转换为判定性问题。例如,将长度为n的序列a分成最多m个连续段,求所有分法中每段和的最大值的最小是多少

    【例题】 1436:数列分段II

 

2.二分查找
      用具有单调性的布尔表达式求解分界点,比如在有序数列中求数字x的排名


3.代替三分
       有时,对于一些单峰函数,我们可以用二分导函数的方法求解函数极值,这时通常将函数的定义域定义为整数域求解比较方便,此时dx可以直接取整数1

四、典型例题

1433:【例题1】愤怒的牛

 
 
 
五、三分

        三分法适用于求解凸性函数的极值问题,二次函数就是一个典型的单峰函数。

        三分法与二分法一样,它会不断缩小答案所在的求解区间。二分法缩小区间利用的原理是函数的单调性,而三分法利用的则是函数的单峰性

       设当前求解的区间为 [l,r] ,令 m=1+(l+r)/3 , m=r-(l+r)/3 , 接着我们计算这两个点的函数值f(m1),f(m2)之后我们将两点中函数值更优的那个点称为好点,函数值较差的那个点称为坏点。我们可以不停缩小求解区间,直至得出近似解

       与二分一样,我们可以指定三分的次数,或是根据 r-1的值来终止

       以求上凸单峰函数的最大值为例,三分的参考程序:

double l=0,r=1e9;
while(r-l>=1e-3)
{
    double m1=l+(r-l)/3;
    double m2=r-(r-l)/3;
    if(f(m1)<f(m2)) l=m1;
    else r=m2;
}

注意:单峰函数强调严格的单调性

 

猜你喜欢

转载自www.cnblogs.com/xiaoyezi-wink/p/10990788.html