NOIP--阿克曼函數的遞歸轉非遞歸解法


  ackerman函數(阿克曼函數,以下簡稱ack函數)是一個雙參數遞歸函數,用遞歸計算代碼如下

int ack(int m,int n)
{    
   if (m==0)        
    return n+1;    
    else if (n==0)        
    return ack(m-1,1);    
    else     return ack(m-1,ack(m,n-1)); }

 


        ack函數像Dirichlet函數一樣,是因為為了澄清某種概念而在數學(計算科學)史有一席之地。 
        ack函數最初是作為一個非線性的鏈式遞歸的例子而被提出來的,它增長很快,事實上m>3時關於n是遠高於線性遞推的指數級增長(關於m增長地更快)而反直覺,即使精確計算ack(4,1)也是做不到的,即使ack(3,3)也有61,如果不記憶化搜索,需要遞歸2000余次才可以計算出來!如果不去考慮ack(3,n)的指數增長的通項而被小數字迷惑企圖直接計算,那么會算得毫無頭緒,所以ack函數被廣泛用於計算機預賽,筆試,數學自主招生考試中。 
        那么既然ack函數增長地如此之快,那么ack(m,1)的反函數增長地極其緩慢了。事實上,路徑壓縮的並查集經過足夠久的查詢,每次查詢你平均復雜度就是反阿克曼函數級別的(也就是log*級別的,至於為什么,我至晚在2012年就想知道這個問題了,現在終於知道…我恐怕短時間內沒法知道(~^~),算法導論里面有對此的推導,有興趣的同學可以去看一下),好吧,這是一些有趣的冷知識,和我和ack函數的歷史淵源,就當隨筆寫出來。 
本以為我和ack的緣分在預賽題中知道它怎么做后就沒有什么新進展了,最多以后講到這個題,但是萬萬沒想到我會以一種奇怪的方式遇到這個函數,科學史上雋永有名的函數例如Dirichlet函數,ack函數果然白發如新。

        最近學習ics里的匯編原理初步和數算的棧實現遞歸方法,事實上這兩者是相通的。我雖然沒有編寫過具體匯編代碼,但是大概原則上知道了怎么把函數調用用堆棧實現,怎么用棧機制非遞歸實現遞歸。紙上得來終覺淺,我決定找一個例題,我編了一個復雜點的題—ackerman函數的非遞歸實現(遞歸函數非遞歸化)。 
經過一番調試調試對了,但是人還是很懵懂,看來還要加強理論學習,不過不得不說這是個很好的例題。


int Ack(int M,int N)
{    
   int top=0,m,n;    
   int stack[10000][4]={{M,N}};//記錄信息m,n,Ack(m,n),跳轉出口種類;    while (true)    {        m=stack[top][0];        n=stack[top][1];        
   if (m==0)            
   stack[top][2]=n+1;        
   else if (n==0)        {            top++;            
   stack[top][0]=m-1;            
   stack[top][1]=1;            
   stack[top][3]=1;            continue;            l1:            
   stack[top][2]=stack[top+1][2];        }        else        {            top++;            
   stack[top][0]=m-1;            top++;            
   stack[top][0]=m;            
   stack[top][1]=n-1;            
   stack[top][3]=2;            
   continue;            l2:            
   stack[top][1]=stack[top+1][2];            
   stack[top][3]=3;            
   continue;            l3:            
   stack[top][2]=stack[top+1][2];        }        
   if (top==0)            
   break;        top--;        
   switch (stack[top+1][3])        {            
   case 1:goto l1;            
   case 2:goto l2;            
   case 3:goto l3;        }    }    return stack[0][2]; }




NOIP信息學視頻地址

視頻地址

鏈接:https://pan.baidu.com/s/1tHo1DFMaDuMZAemNH60dmw 
提取碼:7jgr


免責聲明!

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



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