我在其中一个网站上遇到过这个问题。
要求:
如果给出两个辅助杆而不是一个辅助杆,需要提出算法并解决河内塔问题的时间复杂性。
我的尝试:
河内的原始塔:
T(N)= T(N-1) // Moving N-1 disks from Source to Auxilary
+ 1 // Moving Nth disk from Source to Destination
+ T(N-1) // Moving N-1 disks from Auxilary to Destination
T(N) = 2*T(N-1) + 1
= O(2 power N ) // exponential.
目前的问题是因为我们有两个辅助杆
`
T(N) =
T(N/2) // Moving top N/2 from Source to Aux1
+ T(N/2) // Moving the remaining N/2 from Source to Destination using Aux2.
+ T(N/2) // Moving N/2 from Aux1 to Destination.
T(N) = 3*T(N/2)
=O( 3 power log N base 2 )
= O( N power log 3 base 2 ) // less than quadartic.
但我对此并不十分肯定,因为我不是计算时间为T(N / 2),用于将顶部N / 2移动到Aux1,也用于使用Aux2将botton N / 2从源移动到目的地。
为什么我认为这是不正确的,因为在第一种情况下,当移动顶部(N / 2)时我们可以玩三根杆:Destiation,Aux1& AUX2 但是当移动底部(N / 2)时,我们只能使用两根杆Destination,Aux2
所以我认为应该更好地解决这个问题。
答案 0 :(得分:1)
这是Python中一个简单的memoized递归函数,它使用Frame–Stewart algorithm来查找最小移动次数。根据上面链接的维基百科文章,该算法被证明是4个钉和最多30个磁盘的最佳选择,并且它被认为是n
磁盘和r
的所有组合的最佳选择。钉(但未证明是这样)。它可能会对我的实现进行一些优化,但它的速度足以获得合理的n
和r
值。
def hanoi(n, r, memo={}): # deliberately using a mutable default argument here
"""Return the number of steps required to move n disks using a total of r pegs."""
if n == 1: # base case
return 1
if r <= 2: # impossible cases
return float("inf")
if (n,r) not in memo:
memo[n, r] = min(hanoi(k, r)*2 + hanoi(n-k, r-1) # recursive calls
for k in range(1, n))
return memo[n, r]
答案 1 :(得分:0)
基本情况-
第4步背后的想法是,无论辅助塔的数量如何,都没有更快的方法将大小为2的堆栈传输到目的地。
// Number of rings, from tower, destination tower, 1st auxiliary tower and 2nd auxiliary tower.
void hanoi(int rings, int from, int to, int aux1, int aux2){
if(rings==0)
return;
if(rings==1){
cout<<from<<" to "<<to<<endl;ct++;
return;
}
hanoi(rings-2, from, aux2, aux1, to);
cout<<from<<" to "<<aux1<<endl;
cout<<from<<" to "<<to<<endl;
cout<<aux1<<" to "<<to<<endl;
ct+=3;
hanoi(rings-2,aux2, to, from, aux1);
}
int main(){
int i,n,j,k,l,m;
cin>>n;
hanoi(n,0,1,2,3);
cout<<ct<<endl;
}