您的位置:首页 > 其它

{hanoi塔大集合}hdoj的汉诺塔问题

2013-09-11 17:14 267 查看
普通汉诺塔

H(1)=1;

H(n)=H(n-1)+1+H(n-1)=2*H(n-1)+1;//将最顶层n-1个移至B柱子,把最大的移至C,再把n-1个移至C

解得通项H(n)=2^n-1;

汉诺塔2 hdoj1207

经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。Gardon就收到了一个汉诺塔玩具作为生日礼物。

  Gardon是个怕麻烦的人(恩,就是爱偷懒的人),很显然将64个圆盘逐一搬动直到所有的盘子都到达第三个柱子上很困难,所以Gardon决定作个小弊,他又找来了一根一模一样的柱子,通过这个柱子来更快的把所有的盘子移到第三个柱子上。下面的问题就是:当Gardon在一次游戏中使用了N个盘子时,他需要多少次移动才能把他们都移到第三个柱子上?很显然,在没有第四个柱子时,问题的解是2^N-1,但现在有了这个柱子的帮助,又该是多少呢?

同样规定N个盘子对应答案H(n)

分析一下 相当于把当前的汉诺塔分成三部分:第一部分(去B柱子),第二部分(去C柱子),最大那块(直接去D)

第一部分去B时有两根过渡柱子(C\D),假设这一部分有x个圆盘,移动数目便为H(x)(H(n)为“借助B/C将n个圆盘移到D的步骤数”,同理等于“借助C\D将n个圆盘移到B的步骤数”),递归可解。

第二部分去C时只有一根过渡柱子(D,因为B已经被占领),因此回归普通汉诺塔问题,移动数目为2^y-1(假设这部分y个圆盘,并且y+x=n-1)

最大那块移过D去有一个步骤。

最后再把第二部分移到D

把第一部分移到D

综上H(n)=min{2*(H(x)+2^y-1)}+1;其中(x+y=n-1,x,y<n-1)

或者F(n)=min(2*F(n-r)+2^r-1),(1≤r≤n)。
通过这个方程我们能得到所有4柱汉诺塔的步骤个数,同时也有人证明[1]了,对于四柱汉诺塔,当r=(sqrt(8*n+1)-1)/2时,能保证f(n)取得最小值F(n)=(n-(r^2-r+2)/2)*2^r+1。所以算法的复杂度是F(n)=O(sqrt(2*n)*2^ sqrt(2*n))。从这这个方程中也可以看出,在n<6的时候,我们可以验证是和我们起初的构想的结构是相同的,但是当n再增多时就不是当初想的那样了。
//1.《四柱汉诺塔之初步探究》杨楷 徐川( 北京大学计算机科学与技术系, 北京,
100871) 北京大学学报( 自然科学版)
, 第40 卷, 第1 期,
2004 年1 月

这个问题还可以拓展到n个柱子,通过n-1个柱子的移动来完成递归,复杂度相当大。
可以参见/article/5092756.html的讨论。

汉诺塔3 hdoj2064

约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。

现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。

Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?

依旧分成两部分:最大圆盘<max>+剩下n-1个圆盘<n-1>

抽象过程如下:

1 2
3

<max>+<n-1>

<max>
<n-1>

<max>
<n-1>

<max>
<n-1>

<max>+<n-1>

<n-1>
<max>

<n-1>
<max>

<n-1>
<max>

<n-1>+<max>

其中<n-1>走了三趟(3*H(n-1)),<max>走了一趟(两步)

所以H(n)=3*H(n-1)+2;(n>1)

H(1)=2;

解得H(n)=3^n-1;

PS:使用__int64 与 printf("%I64d",ans);即可,,pow无力做到

汉诺塔4 hdoj2077

还记得汉诺塔III吗?他的规则是这样的:不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到小盘的上面。xhd在想如果我们允许最大的盘子放到最上面会怎么样呢?(只允许最大的放在最上面)当然最后需要的结果是盘子从小到大排在最右边。

圆盘分成三部分:<max>+<max'>{第二大}+<n-2>

抽象过程如下:

1
2 3

<max>+<max'>+<n-2>

<max>+<max'>
<n-2>

<max>+<max'>
<n-2>

<max> <max'>
<n-2>

<max> <max'>+<n-2>

<max'>+<n-2>+<max>{最上面}

<max'>+<n-2>
<max>

<n-2> <max'>
<max>

<n-2> <max>+<max'>

<n-2> <max>+<max'>

<max>+<max'>+<n-2>

摘自http://www.cnblogs.com/jackge/archive/2013/07/26/3218733.html

如果有n个盘子,则需要前n-1个挪到中间的盘子上,然后最大的盘子挪到最右面,需要两步,把前(n-1)个盘子从左边挪到中间是和从中间挪到右边需要相同的次数。而a数组中存放的就是那个前n-1个盘子挪动到相同位置需要的次数。结果即为a[i-1]*2+2。

而求a数组需要用到递推。公式为第i个为前n-1个移动次数的三倍加一,简化到两个盘子,小的先移动两次到最右边,大的移到中间,然后小的在移回中间,小的移动了三次,而大的移动了一次,就使他们全部挪动了一个位置

a[0]=0;a[1]=1;

a[i]=3*a[i-1]+1;

ans=2*a[n-1]+2;

解得H(n)=ans=3^(n-1)+1;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: