算法设计与分析3 - 动态规划解决四柱汉诺塔问题 推荐
2008-09-20 20:01
387 查看
[align=center]三、四柱汉诺塔问题[/b][/b][/align]
3、四塔问题:设有A,B,C,D四个柱子(有时称塔),在A柱上有由小到大堆放的n个盘子,如图所示。
![](../attachment/200809/200809201221911960095.jpg)
今将A柱上的盘子移动到D柱上去。可以利用B,C柱作为工作栈用,移动的规则如下:
①每次只能移动一个盘子。
②在移动的过程中,小盘子只能放到大盘子的上面。
设计并实现一个求解四塔问题的动态规划算法,并分析时间和空间复杂性。
■ 算法思想:
用如下算法移动盘子(记为FourPegsHanoi):
1)、将A柱上n个盘子划分为上下两部分,下方部分共有k(1≤k≤n)个盘子,上方部分共有n - k个盘子。
2)、将A柱上面部分n–k个盘子使用FourPegsHanoi算法经过C、D柱移至B柱。
3)、将A柱剩余的k个盘子使用ThreePegsHanoi算法经过C柱移至D柱。
4)、将B柱上的n–k个盘子使用FourPegsHanoi算法经过A、C柱移至D柱。
ThreePegsHanoi算法如下(设三个柱子分别为A、B、C,A柱上共有k个盘子):
1)、将A柱上方k-1个盘子使用ThreePegsHanoi算法经过B柱移至C柱。
2)、将C柱上最后一个盘子直接移至C盘。
3)、将B柱上k-1个盘子使用ThreePegsHanoi算法经过A柱移至C柱。
■ 算法步骤:
根据动态规划的四个步骤,求解如下:
1)、最优子结构性质:
四柱汉诺塔问题的最优解是用最少的移动次数将A柱上的盘子全部移到D柱上。当盘子总数为i时,我们不妨设使用FourPegsHanoi的最少移动次数为f(i)。相应的ThreePegsHanoi 算法移动次数为g(k),由于g(k)=2g(k-1)+1=2k -1,当k确定时,g(k)也是不变的。
f(i)为最优解时,其子问题f(i-k)也必为最优解。如果f(i-k)不是最优解,那么存在f’(i-k) < f(i-k)。用f’(i-k)替换f(i-k)将产生一个比f(i)更优的解。这与f(i)为最优解是矛盾的。所以本问题具有最优子结构性质。
2)、递归地定义问题的最优解:
根据上述FourPegsHanoi算法得到最少移动次数f(i):
![](../attachment/200809/200809201221911974380.jpg)
3)、自底向上地计算最优解的值:
(相应的Java源程序在Hanoi.java中。)
f(i)对应算法中的m[i ,
s[i]]。
-----------------------------------------------------------------------------------------
求四柱汉诺塔最小移动次数伪代码:
数组下标从0开始,数组m,s大小为n+1。数组m存储计算最小移动次数的中间值。数组s存储每步最小移动次数所对应的分割值k。
MinMovements ( n ):
m[0,0]
← s[0] ← 0 ▹为了方便计算增加了f(0) = m[0,s[0]] = 0
for
i ← 1 to n
do
min ← ∞
for
k ← 1 to i
do
m[i , k] ← 2 * m[i – k , s[i – k]] + 2k – 1
if
m[i , k] < min
then
min ← m[i , k]
s[i] = k
return
m[n , s
] & s
4)、根据计算信息构造最优解:
MinMovements求出的数组s中,s[i]是f(i)所对应的最优分割位置。根据数组s来构造移动盘子的最佳序列,伪代码如下:
-----------------------------------------------------------------------------------------
FourPegsHanoi (i , src, temp1, temp2, dest):
if i = 1
then
move(src , dest)
else FourPegsHanoi(i – s[i] ,
src , temp2 , dest , temp1)
ThreePegsHanoi(s[i] , src ,
temp2 , dest)
FourPegsHanoi(i – s[i] , temp1 , src , temp2 ,
dest)
----------------------------------------------------------------------------------------
ThreePegsHanoi(k , src , temp, dest):
if
k = 1
then
move(src , dest)
else ThreePegsHanoi(k - 1, src , dest ,
temp)
move(src
, dest)
ThreePegsHanoi(k
- 1, temp , src , dest)
-----------------------------------------------------------------------------------------
■
时间空间复杂度分析:
1、时间复杂度
MinMovements算法的时间复杂度为:
T(n) = 1 + 2 + ...[/b]
+ n = n(n+1)/2 = O(n2)
2、空间复杂度
MinMovements算法占用的空间为m 和 s数组的大小:
即 (n+1)2
+ (n+1) = O(n2)
通过分析m数组中记录了一些与结果不相关的数据,所以通过对MinMovements进行改进,可使占用空间减小为O(n)。
MinMovements ( n ):
m[0]
← s[0] ← 0
for
i ← 1 to n
do
m[i] ← ∞
for
k ← 1 to i
do
q ← 2 * m[i – k] + 2k – 1
if
q < m[i]
then
m[i] ← q
s[i] ← k
return
m
& s
■
算法测试
当n=10时,最小移动次数49。 移动序列如下:
当n=15时,最小移动次数129。移动序列如下:
附件:http://down.51cto.com/data/2350666
3、四塔问题:设有A,B,C,D四个柱子(有时称塔),在A柱上有由小到大堆放的n个盘子,如图所示。
![](../attachment/200809/200809201221911960095.jpg)
今将A柱上的盘子移动到D柱上去。可以利用B,C柱作为工作栈用,移动的规则如下:
①每次只能移动一个盘子。
②在移动的过程中,小盘子只能放到大盘子的上面。
设计并实现一个求解四塔问题的动态规划算法,并分析时间和空间复杂性。
■ 算法思想:
用如下算法移动盘子(记为FourPegsHanoi):
1)、将A柱上n个盘子划分为上下两部分,下方部分共有k(1≤k≤n)个盘子,上方部分共有n - k个盘子。
2)、将A柱上面部分n–k个盘子使用FourPegsHanoi算法经过C、D柱移至B柱。
3)、将A柱剩余的k个盘子使用ThreePegsHanoi算法经过C柱移至D柱。
4)、将B柱上的n–k个盘子使用FourPegsHanoi算法经过A、C柱移至D柱。
ThreePegsHanoi算法如下(设三个柱子分别为A、B、C,A柱上共有k个盘子):
1)、将A柱上方k-1个盘子使用ThreePegsHanoi算法经过B柱移至C柱。
2)、将C柱上最后一个盘子直接移至C盘。
3)、将B柱上k-1个盘子使用ThreePegsHanoi算法经过A柱移至C柱。
■ 算法步骤:
根据动态规划的四个步骤,求解如下:
1)、最优子结构性质:
四柱汉诺塔问题的最优解是用最少的移动次数将A柱上的盘子全部移到D柱上。当盘子总数为i时,我们不妨设使用FourPegsHanoi的最少移动次数为f(i)。相应的ThreePegsHanoi 算法移动次数为g(k),由于g(k)=2g(k-1)+1=2k -1,当k确定时,g(k)也是不变的。
f(i)为最优解时,其子问题f(i-k)也必为最优解。如果f(i-k)不是最优解,那么存在f’(i-k) < f(i-k)。用f’(i-k)替换f(i-k)将产生一个比f(i)更优的解。这与f(i)为最优解是矛盾的。所以本问题具有最优子结构性质。
2)、递归地定义问题的最优解:
根据上述FourPegsHanoi算法得到最少移动次数f(i):
![](../attachment/200809/200809201221911974380.jpg)
3)、自底向上地计算最优解的值:
(相应的Java源程序在Hanoi.java中。)
f(i)对应算法中的m[i ,
s[i]]。
-----------------------------------------------------------------------------------------
求四柱汉诺塔最小移动次数伪代码:
数组下标从0开始,数组m,s大小为n+1。数组m存储计算最小移动次数的中间值。数组s存储每步最小移动次数所对应的分割值k。
MinMovements ( n ):
m[0,0]
← s[0] ← 0 ▹为了方便计算增加了f(0) = m[0,s[0]] = 0
for
i ← 1 to n
do
min ← ∞
for
k ← 1 to i
do
m[i , k] ← 2 * m[i – k , s[i – k]] + 2k – 1
if
m[i , k] < min
then
min ← m[i , k]
s[i] = k
return
m[n , s
] & s
4)、根据计算信息构造最优解:
MinMovements求出的数组s中,s[i]是f(i)所对应的最优分割位置。根据数组s来构造移动盘子的最佳序列,伪代码如下:
-----------------------------------------------------------------------------------------
FourPegsHanoi (i , src, temp1, temp2, dest):
if i = 1
then
move(src , dest)
else FourPegsHanoi(i – s[i] ,
src , temp2 , dest , temp1)
ThreePegsHanoi(s[i] , src ,
temp2 , dest)
FourPegsHanoi(i – s[i] , temp1 , src , temp2 ,
dest)
----------------------------------------------------------------------------------------
ThreePegsHanoi(k , src , temp, dest):
if
k = 1
then
move(src , dest)
else ThreePegsHanoi(k - 1, src , dest ,
temp)
move(src
, dest)
ThreePegsHanoi(k
- 1, temp , src , dest)
-----------------------------------------------------------------------------------------
■
时间空间复杂度分析:
1、时间复杂度
MinMovements算法的时间复杂度为:
T(n) = 1 + 2 + ...[/b]
+ n = n(n+1)/2 = O(n2)
2、空间复杂度
MinMovements算法占用的空间为m 和 s数组的大小:
即 (n+1)2
+ (n+1) = O(n2)
通过分析m数组中记录了一些与结果不相关的数据,所以通过对MinMovements进行改进,可使占用空间减小为O(n)。
MinMovements ( n ):
m[0]
← s[0] ← 0
for
i ← 1 to n
do
m[i] ← ∞
for
k ← 1 to i
do
q ← 2 * m[i – k] + 2k – 1
if
q < m[i]
then
m[i] ← q
s[i] ← k
return
m
& s
■
算法测试
当n=10时,最小移动次数49。 移动序列如下:
1 A->D 2 A->B 3 A->C 4 B->C 5 D->C 6 A->B 7 A->D 8 B->D 9 A->B | 10 D->A 11 D->B 12 A->B 13 C->A 14 C->D 15 C->B 16 D->B 17 A->B 18 A->C 19 A->D | 20 C->D 21 A->C 22 D->A 23 D->C 24 A->C 25 A->D 26 C->D 27 C->A 28 D->A 29 C->D | 30 A->C 31 A->D 32 C->D 33 B->C 34 B->D 35 B->A 36 D->A 37 C->A 38 B->D 39 B->C | 40 D->C 41 B->D 42 C->B 43 C->D 44 B->D 45 A->B 46 A->C 47 A->D 48 C->D 49 B->D |
1 A->B 2 A->C 3 A->D 4 C->D 5 B->D 6 A->C 7 A->B 8 C->B 9 A->C 10 B->A 11 B->C 12 A->C 13 D->A 14 D->B 15 D->C 16 B->C 17 A->C 18 A->D 19 A->B 20 D->B 21 A->D 22 B->A 23 B->D 24 A->D 25 A->B 26 D->B | 27 D->A 28 B->A 29 D->B 30 A->D 31 A->B 32 D->B 33 C->D 34 C->B 35 C->A 36 B->A 37 D->A 38 C->B 39 C->D 40 B->D 41 C->B 42 D->C 43 D->B 44 C->B 45 A->C 46 A->D 47 A->B 48 D->B 49 C->B 50 A->D 51 A->C 52 D->C | 53 A->D 54 C->A 55 C->D 56 A->D 57 A->C 58 D->C 59 D->A 60 C->A 61 D->C 62 A->D 63 A->C 64 D->C 65 A->D 66 C->A 67 C->D 68 A->D 69 C->A 70 D->C 71 D->A 72 C->A 73 C->D 74 A->D 75 A->C 76 D->C 77 A->D 78 C->A | 79 C->D 80 A->D 81 B->D 82 B->A 83 B->C 84 A->C 85 D->C 86 B->A 87 B->D 88 A->D 89 B->A 90 D->B 91 D->A 92 B->A 93 C->B 94 C->D 95 C->A 96 D->A 97 B->A 98 B->C 99 B->D 100C->D 101B->C 102D->B 103D->C 104B->C | 105 B->D 106 C->D 107 C->B 108 D->B 109 C->D 110 B->C 111 B->D 112 C->D 113 A->C 114 A->D 115 A->B 116 D->B 117 C->B 118 A->D 119 A->C 120 D->C 121 A->D 122 C->A 123 C->D 124 A->D 125 B->A 126 B->C 127 B->D 128 C->D 129 A->D |
相关文章推荐
- 新兴的云计算能否解决看病难的老问题 推荐
- 多种思路解决Keepalived限制死20个VIP问题 推荐
- leetcode 327. Count of Range Sum 字段和问题 + 动态规划DP解决 + 字段数 + 暴力求解真好
- Android中ListView的item按钮监听错乱问题解决办法 推荐
- 动态规划与数学方程法解决楼层扔鸡蛋问题
- Android studio推荐插件以及升级后插件丢失问题解决
- Exchange 2010无法安装问题解决方法 推荐
- 动态规划解决最大子矩阵问题
- 动态规划解决钢条切割问题
- 动态规划解决矩阵链乘问题的java编码实现
- 动态规划解决0-1背包问题
- 四步解决存储空间滥用问题 推荐
- Windows7焦点丢失问题解决方案和MarkdownPad软件推荐
- docker中遇到的问题及解决方法 推荐
- 方法论之 如何解决一个问题 推荐
- Xen虚拟机加入Puppet环境如何解决时间同步问题 推荐
- 蛙蛙推荐:整理一个树型问题的解决方法。
- 什么是解决问题的思路:超级客服实战 推荐
- 算法设计与分析:第四章 动态规划 4.3多段图的最短路径问题
- 解决Excel打开UTF-8编码的CSV文件乱码的问题 推荐