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
  • 相关阅读:
    [DB] 数据库的连接
    JS leetcode 翻转字符串里的单词 题解分析
    JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
    JS leetcode 搜索插入位置 题解分析
    JS leetcode 杨辉三角Ⅱ 题解分析
    JS leetcode 寻找数组的中心索引 题解分析
    JS leetcode 移除元素 题解分析
    JS leetcode 最大连续1的个数 题解分析
    JS leetcode 两数之和 II
    JS leetcode 反转字符串 题解分析
  • 原文地址:https://www.cnblogs.com/liugl7/p/4889656.html
Copyright © 2011-2022 走看看