zoukankan      html  css  js  c++  java
  • 二分法&三分法

    ural History Exam    二分

     1 #include <iostream>
     2 #include <cstdlib>
     3 using namespace std;
     4 
     5 //二分查找
     6 bool binarySearch(long a[], long x, int n){
     7     int left = 0,right = n-1;
     8     int middle;
     9     while (left <= right){
    10         middle = (left+right)/2;
    11         if (x == a[middle]) return 1;
    12         if (x > a[middle]) left = middle + 1;
    13         else right = middle - 1;
    14     }
    15     return 0;
    16 }
    17 
    18 int cmp(const void *a, const void *b)  {  
    19     return *(int *)a - *(int *)b;  
    20 }  
    21 
    22 int main(){
    23     int numprofessor;
    24     scanf("%ld",&numprofessor);
    25     
    26     long yearProfessor[numprofessor];
    27     for(int i=0;i<numprofessor;i++){
    28         scanf("%ld",&yearProfessor[i]);
    29     }
    30     
    31     qsort(yearProfessor,numprofessor,sizeof(long),cmp);
    32     long numstudent;
    33     scanf("%ld",&numstudent);
    34     
    35     long result=0;
    36     
    37     long yearstudent[numstudent];
    38     for(int i=0;i<numstudent;i++){
    39         scanf("%ld",&yearstudent[i]);
    40         if( binarySearch(yearProfessor, yearstudent[i], numprofessor)){
    41             result++;
    42         }
    43         
    44     }
    45     
    46     cout<<result;
    47         
    48 } 

    二分

    ural Fibonacci Sequence

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

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int i,j,fi,fj,n;
     5 int count=0,count1=0,count2=0;
     6 int finext;           // 表示fi下一个f(i+1)的值 
     7 
     8 int fib1(int j){      /*递归程序1:计算fj时用到的fi和finext的次数  */  
     9       if(j==i){ 
    10             count1++;   //记录fi用到的次数 
    11           return 1; 
    12       }
    13       if(j==i+1){
    14             count2++;   //记录finext用到的次数 
    15             return 1;
    16       }  
    17       return  fib1(j-1) + fib1(j-2);
    18 }
    19 
    20 long fib3 (int n){
    21     //* 迭代解法:这里算法复杂度显然为O(n) ,
    22    // 这个解法目前来看是最好的解法,算法既不复杂,而且在时间复杂度和空间复杂度上都有保证  
    23     if(n==i){
    24         return fi;
    25     }   
    26     if(n==i+1){
    27         return finext;
    28     }
    29     long long x = fi, y = finext;
    30     for (int a= i; a<n-1; a++){
    31          y = x + y;
    32          x = y - x;
    33     }
    34     return y;
    35 }
    36  
    37 int main(){
    38     cin>>i>>fi>>j>>fj>>n;
    39     if(j<i){
    40         int temp=j,temp1=fj;
    41         j=i;
    42         fj=fi;
    43         i=temp;
    44         fi=temp1;
    45     } 
    46     int a=fib1(j);
    47     finext=(fj-count1*fi)/count2;
    48     cout<<fib3(n)<<endl;
    49     
    50 }

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

     1 #include <iostream>
     2 using namespace std;
     3 
     4 const long long NLAR = 2000000000;
     5 long long i,fi,j,fj,n;
     6 
     7 int main(){  
     8     cin >> i >> fi >> j >> fj >> n;
     9     if(j<i){     //保证j>i 
    10         int temp=j,temp1=fj;
    11         j=i;
    12         fj=fi;
    13         i=temp;
    14         fi=temp1;
    15     }
    16     
    17     // cal f[i+1]
    18     
    19     long long left=-NLAR, right=NLAR, mid;
    20     long long ti=fi, tj=mid, t;
    21     while (left+1<right){
    22         mid = (left+right)/2;
    23         ti=fi; tj=mid;
    24         for (int k=i+2; k<=j; ++k){
    25             t=ti+tj; 
    26             ti=tj;
    27              tj=t;
    28             if(t>NLAR*2 ||t<-NLAR*2) break;
    29         }
    30         if(tj>=fj) right = mid;
    31             else left=mid;
    32     }
    33 
    34     ti=fi; tj=right;
    35     if(n>i){
    36         for(int k=i+2;k<=n;++k){
    37             t=ti+tj; 
    38             ti=tj; 
    39             tj=t;  
    40         }    
    41         cout << tj << endl;
    42     }
    43     else {
    44         for(int k=i-1; k>=n; ++k){
    45             t=tj-ti; 
    46             tj=ti; 
    47             ti=t;
    48         }
    49         cout << ti << endl;
    50     }
    51 
    52     return 0;
    53 }

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

    ural Bookshelf

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

     

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <iomanip> 
     4 #include <cmath>
     5 using namespace std;
     6 #define EPS 1e-9
     7 
     8 int h,H,L;
     9 double fx(double x){
    10     return H/2.0*x/sqrt(h*h+x*x)-x;    
    11 }
    12 
    13 int main(){
    14     cin>>h>>H>>L;
    15     double left=0,right=H;
    16     long double isover=1;
    17     
    18     while(isover>EPS){
    19         double m1=left+(right-left)/3;
    20         double m2=right-(right-left)/3;
    21         
    22         double fm1=fx(m1);
    23         double fm2=fx(m2);
    24         
    25         if(fm1<fm2) left=m1;
    26         else  right=m2;
    27         isover=right-left;
    28     }
    29     cout<<fixed<<setprecision(6)<<fx(right)<<endl; 
    30 } 

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

     1 /*
     2  * poj-1064 Cable master.cpp
     3  *      二分, 化为整数存储,下界为1(cm),上界为最长绳的长度
     4  *
     5  */
     6 #include<cstdio>
     7 using namespace std;
     8 
     9 const double eps = 1e-7;    //注意精度
    10 const int maxn = 10000 + 10;
    11 
    12 int n, k, cable[maxn];
    13 
    14 int main(){
    15     scanf("%d%d", &n, &k);
    16     double ftmp;
    17     int tmpMax = 0;
    18     for(int i=0; i<n; i++){
    19         scanf("%lf", &ftmp);
    20         cable[i] = int((ftmp+eps) * 100);    //精度
    21 
    22         if(cable[i] > tmpMax) tmpMax = cable[i];
    23     }
    24 
    25     int up = tmpMax, low = 1, mid = -1, ans = -1;
    26     int tmpNum = 0;
    27     while(low <= up){
    28         mid = (up + low) / 2;
    29         tmpNum = 0;
    30         for(int i=0; i<n; i++)
    31             tmpNum += cable[i] / mid;
    32 
    33         if(tmpNum >= k){
    34             if(mid > ans) ans = mid;
    35             low = mid + 1;
    36         }
    37         else
    38             up = mid - 1;
    39     }
    40 
    41     if(ans < 1)
    42         printf("0.00
    ");
    43     else
    44         printf("%.2lf
    ", ans * 0.01);
    45 
    46 
    47     return 0;
    48 }
    poj1064
  • 相关阅读:
    Activity(二)
    channelartlist标签的使用
    把数据保存到数据库附加表 `dede_addonarticle` 时出错,请把相关信息提交给DedeCms官方。Duplicate entry '2' for key 'PRIMARY'
    TP5.0验证器使用方法
    TP5.0登录验证码实现
    dede列表页限制标题长度
    dede搜索页做法
    表单正则验证简便方法
    解决织梦dedecms文档关键字(自动内链)php5.5以上失效的问题 urf-8版本的
    织梦dede解决“更新数据库archives表时出错"方法
  • 原文地址:https://www.cnblogs.com/liugl7/p/4889656.html
Copyright © 2011-2022 走看看