hanio 塔和遞規的理解。


java:
沒什麼好說,問題分解爲子問題的組合。子問題必須到某個規模是可解。
看最先本身的思路,基本ok。就是要簡潔處理下。
重要的是這部
movehan(source, des, temp,count-1); int obj=source.pop(); LSLog.printLine(obj+":"+source.tipString+ " move "+des.tipString+".", 1); des.push(obj);
要注意,這行代碼上面的movehan(xxx)是已經完成的動做。不是假設性動做。而是肯定性動做。因此才能夠source.pop();
public static class hanluota
    {
        public static void test()
        {
            MyStack<Integer> source=new MyStack<Integer>();
            MyStack<Integer> temp=new MyStack<Integer>();
            MyStack<Integer> des=new MyStack<Integer>();
            
            source.push(4);
            source.push(3);
            source.push(2);
            source.push(1);
            
            source.tipString="A";
            temp.tipString="B";
            des.tipString="C";
            
            movehan(source, temp, des, source.size());
        }
        
        //分解問題:s(n-1)->temp.   t(n)->des, temp(n-1)->s.
        public static void movehan(MyStack<Integer> source,MyStack<Integer> temp,MyStack<Integer> des,int count)
        {
            //基本問題
            if(count==1)
            {
                int obj= source.pop();
                des.push(obj);
                LSLog.printLine(obj+":"+source.tipString+ " move "+des.tipString+".", 1);
            }
            else {
                movehan(source, des, temp,count-1);
                int obj=source.pop();
                LSLog.printLine(obj+":"+source.tipString+ " move "+des.tipString+".", 1);
                des.push(obj);
                movehan(temp, source, des,count-1);
            }
        }
    }

 







//遞規很好理解,可是初看hanoi的時候,總沒有理所固然的感受.
//那應該是對遞規根本還沒理解吧.仔細想了下.有點總結.


後來翻到 <<數據結構>> 112頁,原來hanio的程序在這裏解釋了.基本和本身的思考結果一致.只是書中更簡練.
書中提到的接口一致,不知道包不包括,函數能夠運行的條件. 又想了想,可能真的不須要去關心函數能夠運行的條件,
只要關心函數接口一致,但保證子問題和肯定組合中的,肯定是真的肯定.
也就是這個move(n,x,y),只要你n-1移走了.n 必定能夠移動.
赫赫,好像稍微更清楚了一點.
 



//先從咱們熟悉的 從1加到100.這種遞規分析起把.

int main() { //int answer=qestion(100); //printf("%d",answer); qestion2(3,'x','y','z'); }


//------------------基本思路:分解問題,減低次數, 直到某次問題再也不是問題,讓總問題變成 [新問題]和[肯定]的組合
//[總問題],[新問題],[次小問題],[最小問題(不是問題)] //總問題分解,並減小難度 //分解爲[肯定]和[新問題]組合, 而新問題本質和老問題同樣,而且知足老問題的解決方案的條件。 //肯定[新問題]達到某個問題時,裏面的問題,按照規定,是肯定解。這個某個問題就是[次小問題]。 //裏面的問題就是[最小問題],[最小問題],按照規定,是肯定解。 //因此只要[最小問題]是肯定解,依賴最小問題的次小問題([肯定]和[最小問題]組合)必定有解,以致[總問題]。 //ps:([新問題],[次小問題]本質同樣。只是次小問題中的問題再也不是問題)

//總問題 1+2+3+...+100= ? //分解並下降難度,總問題分解爲 // [1+2+3+...99] + [100] // [新問題] + [肯定] // 總問題的目的是累加,基本沒有條件,新問題不存在條件缺失。 //到達 1+2這個問題時候,1+2是次小問題,而裏面的問題1,再也不是問題。1是最小問題。 int qestion(int n) { int answer=0; if(n>1) { answer=n+qestion(n-1);//問題分解,減低難度 分解爲 [肯定] +[問題] } // (2==n)//次小問題。 由於[新問題],[次小問題]本質同樣,只是方便肯定最小問題而已,註釋掉。 // { // answer=2+qestion(1);//qestion(1) 是最小問題,按照常識:1+question(1-1),是肯定解爲1。 // } if(1==n)//最小問題。 { answer=1;//1+question(1-1) 按規定是1。直接寫肯定,終止遞規。 } return answer; } //總問題 從x移動n塊盤到y。用z中轉。 //分解並下降難度,總問題分解爲 // [從x移動n-1快盤到z,用y中轉] +[從x移動n到y] + [從z移動n-1快盤到y,x中轉] // [新問題] + [肯定] + [新問題]。 // 總問題的條件是,y和z是空柱子,第一個新問題,y,z都空知足一樣條件,第二個新問題x空柱子。y柱子有第n盤。但根據遊戲規則。n最大,y能夠看做空柱子。 // 以後全部的新問題都知足條件。由於n-i塊在柱子中間跳來跳去的時候,3個柱子存留的盤是>=n-i+1的,能夠看做 空柱子。 //到達 n=2,只有2個盤的時候,發現這個次小問題 [從x移動2-1快盤到z,用y中轉] +[從x移動n到y] + [從z移動2-1快盤到y,x中轉] // 裏面的全部問題都不在是問題,由於n-1,變成了2-1. // [從x移動2-1快盤到z,用y中轉]。原來須要中轉的問題變成了,移動1塊盤的問題了。移動1塊再也不是 問題了。 void qestion2(int n,char x,char y,char z) { if(n>1)//問題分解,減低難度.分解爲 [問題] +[肯定] +[問題] { qestion2(n-1,x,z,y); move(n,x,y); qestion2(n-1,z,y,x); } // (2==n) // { // ////次小問題。由於 qestion2(2-1,x,z,y),不是問題了。看看他的意思,移動一塊盤,從x到z。v作中轉,一塊盤不須要中專了,這不是問題。 // qestion2(2-1,x,z,y);//因此 qestion2(2-1,x,z,y)。當n等於1的時候,由問題改成肯定方案move(1,x,z); // move(2,x,y);// // qestion2(2-1,z,y,x);//move(1,z,y) // } if(1==n) { move(1,x,y);//question2(1,x,y,z),按常識,移動一塊,至關於move(1,x,y),直接肯定。 } } void move(int n,char x,char y) { printf("[%d]f:%c->%c\n",n,x,y); }
相關文章
相關標籤/搜索