算法高效技巧之打表


 

打表是一種典型的用空間換時間的技巧,一般指將所有可能需要用到的結果事先計算出來,這樣后面需要用到時就可以直接查表獲得。打表常見的用法有如下幾種:

  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;
}

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM