二分查找
例题一:
题目来源: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; }
例题三:
题目大意:有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) 编辑 收藏 举报