• 算法高效技巧之打表


    打表是一种典型的用空间换时间的技巧,一般指将所有可能需要用到的结果事先计算出来,这样后面需要用到时就可以直接查表获得。打表常见的用法有如下几种:

      1、在程序中一次性计算出所有需要用到的结果,之后的查询直接取这些结果。

       这个是最常用到的用法,例如在一个需要查询大量Fibonacci数F(n)的问题中,显然每次从头开始计算是非常耗时的,对Q次查询会产生O(nQ)的时间复杂度;而如果进行预处理,即把所有Fibonacci数预先计算并存在数组中,那么每次查询就只需O(1)的时间复杂度,对Q次查询就值需要O(n+Q)的时间复杂度(其中O(n)是预处理的时间)。

      2、在程序B中分一次或多次计算出所有需要用到的结果,手工把结果写在程序A的数组中,然后在程序A中就可以直接使用这些结果。

      这种用法一般是当程序的一部分过程小号的时间过多,或是没有想到好的算法,因此在另一个程序中使用暴力算法去i出结果,这样就能直接在源程序中使用这些结果。例如对n皇后问题来说,如果使用的算法不够好,就容易超时,而可以在本地用程序计算付出对所有n来说n皇后问题的方案数,然后把算出的结果直接卸载数组中,就可以根据题目输入的n来直接输出结果。

      3、对一些感觉不会做的题目,先用暴力程序计算小范围数据的结果,然后找规律,或许就能发现一些“蛛丝马迹”。

      这种用法在数据范围非常大时候容易用到,因为这样的题目可能不是用直接能想到的算法来解决的,而需要寻找一些规律才能得到结果。

      例题:PAT乙级1044火星数字

      

      

    火星人是以13进制计数的:
    
    地球人的0被火星人称为tret。 
    地球人数字1到12的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep, oct, nov, dec。 
    火星人将进位以后的12个高位数字分别称为:tam, hel, maa, huh, tou, kes, hei, elo, syy, lok, mer, jou。
    
    例如地球人的数字“29”翻译成火星文就是“hel mar”;而火星文“elo nov”对应地球数字“115”。为了方便交流,请你编写程序实现地球和火星数字之间的互译。
    
    输入格式:
    
    输入第一行给出一个正整数N(<100),随后N行,每行给出一个[0, 169)区间内的数字 —— 或者是地球文,或者是火星文。
    
    输出格式:
    
    对应输入的每一行,在一行中输出翻译后的另一种语言的数字。
    
    输入样例:
    
    4
    29
    5
    elo nov
    tam
    输出样例:
    
    hel mar
    may
    115
    13

      思路:写一个初始化函数,把所有的结果保存下来,在main函数中直接找我们所需要的数字即可。具体代码如下:

      

    #include <iostream>
    #include <string> 
    #include <cstdio>
    #include <map>
    using namespace std;
    string unitDigit[13]={"tret","jan","feb","mar","apr","may","jun","jly","aug","sep","oct","nov","dec"};
    string tenDigit[13]={"tret","tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mer","jou"};
    string numToStr[170];//数字->火星文
    map<string,int> strToNum;//火星文->数字
    void init(){
      for(int i=0;i<13;i++){
        numToStr[i]=unitDigit[i];//个位是[0,12],十位为0
        strToNum[unitDigit[i]]=i;
        numToStr[i*13]=tenDigit[i];//十位是[0,12],个位是0
        strToNum[tenDigit[i]]=i*13; 
      }
      //以下是除个位数和整十位数之外的转换 
      for(int i=1;i<13;i++){//十位 
        for(int j=1;j<13;j++){//个位 
          string str=tenDigit[i]+" "+unitDigit[j];
          numToStr[i*13+j]=str;
          strToNum[str]=i*13+j;
        }
      }
    } 
    int main(){
      init();//打表 
      int N;
      scanf("%d%*c",&N);
      for(int i=0;i<N;i++){
        string str;
        getline(cin,str);
        if(str[0]>='0'&&str[0]<='9'){//数字 则转换为int数字
          int num=0;
          for(int i=0;i<str.size();i++){
            num=num*10+(str[i]-'0');
          }
          cout<<numToStr[num]<<endl;    
        }else{
          cout<<strToNum[str]<<endl;
        }
      }
      
      return 0;
    }

      

      

  • 相关阅读:
    Daily Recording 2020/01/09(关键词:1月01版,RouterScan)
    SQL语句技巧(转)
    实施的WinForms键盘快捷键方法
    日常问题汇总(1) 分组筛选
    设计模式 创建型设计模式
    TSQL查询逻辑查询处理
    无法嵌入互操作类型错误处理
    设计模式 创建模式
    设计模式 结构模式
    设计模式 行为模式
  • 原文地址:https://www.cnblogs.com/hxtblogs/p/7654635.html
Copyright © 2020-2023  润新知