二分法&三分法

时间:2023-03-08 16:51:58

ural History Exam    二分

 #include <iostream>
#include <cstdlib>
using namespace std; //二分查找
bool binarySearch(long a[], long x, int n){
int left = ,right = n-;
int middle;
while (left <= right){
middle = (left+right)/;
if (x == a[middle]) return ;
if (x > a[middle]) left = middle + ;
else right = middle - ;
}
return ;
} int cmp(const void *a, const void *b) {
return *(int *)a - *(int *)b;
} int main(){
int numprofessor;
scanf("%ld",&numprofessor); long yearProfessor[numprofessor];
for(int i=;i<numprofessor;i++){
scanf("%ld",&yearProfessor[i]);
} qsort(yearProfessor,numprofessor,sizeof(long),cmp);
long numstudent;
scanf("%ld",&numstudent); long result=; long yearstudent[numstudent];
for(int i=;i<numstudent;i++){
scanf("%ld",&yearstudent[i]);
if( binarySearch(yearProfessor, yearstudent[i], numprofessor)){
result++;
} } cout<<result; }

二分

ural Fibonacci Sequence

第一遍用递归写,结果在数据比较大时,超时了。题目要求1000ms,测试结果是1029ms,代码如下:

 #include <iostream>
using namespace std; int i,j,fi,fj,n;
int count=,count1=,count2=;
int finext; // 表示fi下一个f(i+1)的值 int fib1(int j){ /*递归程序1:计算fj时用到的fi和finext的次数 */
if(j==i){
count1++; //记录fi用到的次数
return ;
}
if(j==i+){
count2++; //记录finext用到的次数
return ;
}
return fib1(j-) + fib1(j-);
} long fib3 (int n){
//* 迭代解法:这里算法复杂度显然为O(n) ,
// 这个解法目前来看是最好的解法,算法既不复杂,而且在时间复杂度和空间复杂度上都有保证
if(n==i){
return fi;
}
if(n==i+){
return finext;
}
long long x = fi, y = finext;
for (int a= i; a<n-; a++){
y = x + y;
x = y - x;
}
return y;
} int main(){
cin>>i>>fi>>j>>fj>>n;
if(j<i){
int temp=j,temp1=fj;
j=i;
fj=fi;
i=temp;
fi=temp1;
}
int a=fib1(j);
finext=(fj-count1*fi)/count2;
cout<<fib3(n)<<endl; }

回想了一下最近学习的二分法,发现暴力枚举后得二分优化,貌似可以过,遂有下代码:

 #include <iostream>
using namespace std; const long long NLAR = ;
long long i,fi,j,fj,n; int main(){
cin >> i >> fi >> j >> fj >> n;
if(j<i){ //保证j>i
int temp=j,temp1=fj;
j=i;
fj=fi;
i=temp;
fi=temp1;
} // cal f[i+1] long long left=-NLAR, right=NLAR, mid;
long long ti=fi, tj=mid, t;
while (left+<right){
mid = (left+right)/;
ti=fi; tj=mid;
for (int k=i+; k<=j; ++k){
t=ti+tj;
ti=tj;
tj=t;
if(t>NLAR* ||t<-NLAR*) break;
}
if(tj>=fj) right = mid;
else left=mid;
} ti=fi; tj=right;
if(n>i){
for(int k=i+;k<=n;++k){
t=ti+tj;
ti=tj;
tj=t;
}
cout << tj << endl;
}
else {
for(int k=i-; k>=n; ++k){
t=tj-ti;
tj=ti;
ti=t;
}
cout << ti << endl;
} return ;
}

三分法主要求解单峰函数极值,

ural Bookshelf

本题目中要求的函数的图像(取H=6,h=1)为:可以看出这是一个单峰函数,可以运用三分法求极值。

二分法&三分法

 #include <iostream>
#include <cstdlib>
#include <iomanip>
#include <cmath>
using namespace std;
#define EPS 1e-9 int h,H,L;
double fx(double x){
return H/2.0*x/sqrt(h*h+x*x)-x;
} int main(){
cin>>h>>H>>L;
double left=,right=H;
long double isover=; while(isover>EPS){
double m1=left+(right-left)/;
double m2=right-(right-left)/; double fm1=fx(m1);
double fm2=fx(m2); if(fm1<fm2) left=m1;
else right=m2;
isover=right-left;
}
cout<<fixed<<setprecision()<<fx(right)<<endl;
}

这里再收录一个关于二分法的课堂例题,poj1064

 /*
* poj-1064 Cable master.cpp
* 二分, 化为整数存储,下界为1(cm),上界为最长绳的长度
*
*/
#include<cstdio>
using namespace std; const double eps = 1e-; //注意精度
const int maxn = + ; int n, k, cable[maxn]; int main(){
scanf("%d%d", &n, &k);
double ftmp;
int tmpMax = ;
for(int i=; i<n; i++){
scanf("%lf", &ftmp);
cable[i] = int((ftmp+eps) * ); //精度 if(cable[i] > tmpMax) tmpMax = cable[i];
} int up = tmpMax, low = , mid = -, ans = -;
int tmpNum = ;
while(low <= up){
mid = (up + low) / ;
tmpNum = ;
for(int i=; i<n; i++)
tmpNum += cable[i] / mid; if(tmpNum >= k){
if(mid > ans) ans = mid;
low = mid + ;
}
else
up = mid - ;
} if(ans < )
printf("0.00\n");
else
printf("%.2lf\n", ans * 0.01); return ;
}

poj1064