分治搜索(二分,三分)

分治搜索

这里写图片描述
所谓分治,就是将一个大事物分解成若干个易解决小事件。然后再将小事件组合起来就得到了大事件的解了。

1.二分搜索:

其中二分搜索是最经典的分治算法。在一个有序连续的单元内,给定键值便可以找到其位置。
算法复杂度O(logN)由此可见其查找的高效性。
接下来结合代码分析:

int BS(int a[],int length,int key)
{
    int left=0,right=length-1;
    while(left<=right)
    {
        int mid=(left+right)/2;
        //最终区间会缩小到mid上;因为最后left=right;
        if(key<mid)
            right=mid-1;
        else
            if(key==mid)
            return mid;
            else
            left=mid+1;
    }
    return -1;
}

例题练习:http://acm.hdu.edu.cn/showproblem.php?pid=2199
求1~100内方程的解,很明显这是一个增函数。符合有序的搜索条件。
二分搜索。

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
double y;

int main()
{
   int t;
   scanf("%d",&t);
   while(t--)
   {
       scanf("%lf",&y);
       double left=0,right=100,mid;
       if(y>=6&&y<=807020306)
       {
           double t=8*mid*mid*mid*mid+ 7*mid*mid*mid+ 2*mid*mid+ 3*mid+ 6;
           while(fabs(y-t)>0.00001)
          {
              mid=(right+left)/2.0;
              t=8*mid*mid*mid*mid+ 7*mid*mid*mid+ 2*mid*mid+ 3*mid+ 6;
              if(t==y) break;
              if(t>y)
             {
                 right=mid;
             }
             else
             {
              left=mid;
            }
        }
          printf("%.4lf\n",mid);
       }
       else
        printf("No solution!\n");


   }
    return 0;
}

2.三分搜索

我们都知道 二分查找 适用于单调函数中逼近求解某点的值。
如果遇到凸性或凹形函数时,可以用三分查找求那个凸点或凹点,寻找最值得时候,三分就体现出他巨大的威力。
这里有一篇讲的比较好的博客可以给大家推荐一下:
http://blog.csdn.net/pi9nc/article/details/9666627
我也重新实践一下:

int TS()
{
    int left=0,right=100,mid;
    while(left<right-1)
    {
        mid=(left+right)/2;
        int mmid=(mid+right)/2;
        if(fun(mid)<fun(mmid))
            right=mmid;
        else
            left=mid;
    }
    return mid;
}

给一个经典的例题参考:
http://acm.hdu.edu.cn/showproblem.php?pid=2899

就是找最小值。
AC代码:

#include <cstdio>
#include <cmath>
using namespace std;
double ThreeDivide(double x,double Y)
{
    return 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*pow(x,2)-Y*x;       
}

int main()
{
    int T,i;
    double Y,left,rigth,mid,mmid;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lf",&Y);
        left=0,rigth=100;
        for (i=1;i<=200;i++)
        {
            mid=(left+rigth)/2;
            mmid=(mid+rigth)/2;
            if (ThreeDivide(mid,Y)<ThreeDivide(mmid,Y))
                rigth=mmid;
            else
                left=mid;
        }
        printf("%.4lf\n",ThreeDivide(mid,Y));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值