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