二分查找

来源:互联网 发布:羞辱2优化补丁 编辑:程序博客网 时间:2024/05/17 11:56

二分查找:

例题一:

题目来源: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 550int 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;}


1 0
原创粉丝点击