二分查找

二分查找:

例题一:

题目来源:HDOJ-2199:Can you solve this equation?

题目大意:给出一个方程8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,再给出一个Y。求出0~100之间的解。

题目分析:最基础的二分查找问题。

AC代码:

#include <stdio.h>
#include <math.h>
double f(double x)
{
       return 8*pow(x,4)+7*pow(x,3)+2*pow(x,2)+3*x+6;
}
double abs(double a)		//求绝对值
{
       return a>0?a:-a;
}
int main()
{
       int t;
       double y,left,right,mid;
       scanf("%d",&t);
       while(t--)
       {
              scanf("%lf",&y);
              if(y<f(0)||y>f(100))              //比較端点函数值
              {
                     puts("No solution!");
                     continue;
              }
              else
              {
                     left=0;right=100;
                     while(right-left>1e-8)     //对于double类型的值,应尽量减小误差
                     {
                            mid=(left+right)/2;
                            if(abs(f(mid)-y)<1e-8)
                                   break;
                            if((f(mid)-y)>1e-8)
                                   right=mid;
                            else
                                   left=mid;
                     }
              }
              printf("%.4lf\n",mid);
       }    
       return 0;
}


例题二:

题目来源:HDOJ-2141:Can you find it?

题目大意:给你三个有序数列A, B, C,再给出一个数字 X. 是否能找到三个数字Ai, Bj, Ck, 使得 Ai+Bj+Ck = X.

题目分析:最基础的二分查找问题。避免超时,进行优化,先合并两个数组再进行查找。

AC代码:

#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define C 550
int L[C],N[C],M[C];
int LN[C*C];
int find(int LN[],int k,int y)           //二分查找
{
       int left=0,right=k-1,mid;
       while(left<=right)
       {
              mid=(left+right)/2;
              if(LN[mid]==y)
                     return1;
              if(LN[mid]>y)
                     right=mid-1;
              else
                     left=mid+1;
       }
       return 0;
}
int main()
{
       int l,n,m,s,i,j,k;
       int num=1,x,y,q;
       while(~scanf("%d%d%d",&l,&n,&m))
       {
              k=0;
              for(i=0;i<l;i++)
                     scanf("%d",&L[i]);
              for(i=0;i<n;i++)
                     scanf("%d",&N[i]);
              for(i=0;i<m;i++)
                     scanf("%d",&M[i]);
              for(i=0;i<l;i++)
                     for(j=0;j<n;j++)
                            LN[k++]=L[i]+N[j];             //合并L和N
              sort(LN,LN+k);            //对LN数组排序
              scanf("%d",&s);
              printf("Case %d:\n",num++);
              while(s--)
              {
                     q=1;        // q为标记,1为找不到,0为能找到
                     scanf("%d",&x);
                     for(i=0;i<m;i++)
                     {
                            y=x-M[i];              //由于L+N+M=x。所以x-M=LN=y
                            if(find(LN,k,y))             //在LN数组中查找到y
                            {
                                   puts("YES");
                                   q=0;
                                   break;
                            }
                     }
                     if(q)        // 找不到y
                            puts("NO");
              }
       }
       return 0;
}


例题三:

题目来源:HDOJ-1551:Cable master

题目大意:有n段长度不等的电缆。要求分成最大长度的k段长度相等的电缆

题目分析:主要的二分查找,寻找最合适的长度。

AC代码:

#include <stdio.h>
double a[100100];
int n,k,i;
bool find(double x)        //等长度的电缆段数是否符合要求,并且是否为最长的电缆
{
       int sum=0;
       for(i=0;i<n;i++)
              sum+=(int)(a[i]/x);
       return sum>=k;
}
int main()
{
       double left,right,mid;
       while(scanf("%d%d",&n,&k),n||k)
       {
      
              for(i=0;i<n;i++)
                     scanf("%lf",&a[i]);
              left=0;
              right=100000;
              while(right-left>1e-8)            //推断是否符合要求
              {
                     mid=(left+right)/2;
                     if(find(mid))          //电缆不是最长
                            left=mid;
                     else         //电缆段数不够
                            right=mid;
              }
              right=(int)(right*100)/100.0;         //right。mid,left都符合要求。可是right是最大的,更符合要求。
              printf("%.2lf\n",right);          //并且不能四舍五入。防止电缆不够
       }
       return 0;
}


posted on 2018-01-31 10:38  yjbjingcha  阅读(73)  评论(0编辑  收藏  举报

导航