This article takes you through the tower of Hanoi and its deformation problems

Keywords: C++ Algorithm Back-end Math

Ordinary Hanoi Tower

Interested children's shoes can contact and communicate with me~
Official account: swim the code sea more high quality original articles are inside!

The Tower of Hanoi is a mathematical problem based on a legend:

There are three poles A, B and C. There are N (N > 1) perforated discs on rod A, and the size of the disc decreases from bottom to top. It is required to move all discs to the c-rod according to the following rules:

  1. Only one disc can be moved at a time;
  2. The large plate cannot be stacked on the small plate.

The disc can be temporarily placed on rod B, or the disc removed from rod A can be moved back to rod A, but the above two rules must be followed.

For this problem, we can start from a simple point of view, and then find the law. Find a way to solve this problem from the law. Hanoi tower is usually used as an introductory case for learning recursion. This article will thoroughly understand the subject of Hanoi Tower thought and its deformation.

We started when there was only one plate. It's very simple. Just move the red plate to B.

Now let's study two plates:

  • Our idea is to put the bottom big plate on B first, but because the plates are different in size, we have to find a way to put the upper plate on C first, so that we can put the lower big plate on B, and then put the upper small plate on B

Steps:

1. Red plate moved to C upper
2. Yellow plate moved to B upper
3. Red plate moved to B upper

At this time, both plates are on B, and the red plate is on the yellow plate

Next, let's look at the three plates

  • To put them all on B, we must first find a way to move the two plates above blue to C, so as to move the blue plate to B. Therefore, first move the red and yellow to C. now the problem becomes that there are only two plates, and the above three steps are used. Then move the blue plate to B. Finally, move the yellow and red plates to B, which returns to the case where there are only two plates above.

Steps:

1. Move the red plate to B upper
2. Move the yellow plate to C upper
3. Move the red plate to C upper
4. Move the blue plate to B upper
5. Move the red plate to A upper
6. Move the yellow plate to B upper
7. Move the red plate to B upper

It can be seen that the situation of three plates can be transformed into that of two plates, and then it can be solved.

According to the above rules:

N plates move from A to B = first move n - 1 plates from A to C + move the bottom plate to B + and finally move n - 1 plates from C to B

Namely: formula H (n) = H (n - 1) + 1 + H (n - 1)

The mathematical method is suitable for calculating the number of moves, and the recursive method can calculate the number of times and display the moving path, the same later.

Now the idea is clear. Let's talk about two solutions:

Solution 1 (mathematical method):

//Substitution + mathematical induction

H( n ) = H( n - 1 ) + 1 + H( n - 1 )
	   = 2 * H( n - 1 )  +  1
//Add 1 on both sides at the same time
H( n ) + 1 = 2 * [ H( n - 1 ) + 1 ]
//Let u (n) = H (n) + 1
H( n ) + 1 = 2 * [ H(n - 1 ) + 1 ]
//Then it becomes
U( n ) = 2 * U( n - 1 )    
       = 2^2 * U( n - 2 ) = ······
       = 2^(n-1) * U(1) = 2^n
//Therefore, the solution is h (n) = 2 ^ n - 1

Solution 2 (recursive method):

unsigned int count = 0;
void hanio(int n,char A,char B,char C){
    
	if(n==1)
	   cout<<"Put "<<n<<" from "<<A<<" to "<<B<<endl;// If there is only one, just put this plate directly on B
       count += 1;
	else
	{
	   hanio(n-1,A,C,B);    //Move the first n-1 plates from A to C with the help of B
	   cout<<"Put "<<n<<" from "<<A<<" to "<<B<<endl;	//Move the bottom plate from A to B
       count += 1;
	   hanio(n-1,C,B,A);   //Move the n-1 plates above from C to B with the help of A
}

Deformation question 1 (change conditions):

If there are 2N plates, there are N types of plates, and there are two plates of each type (these two plates are exactly the same size and color)

Train of thought: in the past, move one plate: for example, move red to C. now it's nothing more than moving two red plates to C. because the two plates are exactly the same, you just need to move the original plate once and now move it twice

New 2n tray moves from A to B = 2 * number of previous n tray moves

Therefore, there are still two solutions:

Solution 1 (mathematical method):

//Substitution + mathematical induction
//G(n) represents the number of moves under the new rule
G( n ) = 2 * H( n )
	   = 2 * ( 2^n - 1 )
       = 2^(n + 1) - 2

Solution 2 (recursive method):

unsigned int count = 0;
void hanio(int n,char A,char B,char C){
    
	if(n == 2 ){
	   cout<<"Put "<<n<<" from "<<A<<" to "<<B<<endl;// If there are only two, just put these two plates directly on B
       cout<<"Put "<<n-1<<" from "<<A<<" to "<<B<<endl;
       count += 2;
    }
	else
	{
	   hanio(n-2,A,C,B);    //Move the first n-2 plates from A to C with the help of B
	   cout<<"Put "<<n - 1<<" from "<<A<<" to "<<B<<endl;	//Move the bottom two plates from A to B
       cout<<"Put "<<n<<" from "<<A<<" to "<<B<<endl;	//
       count += 2;
	   hanio(n-2,C,B,A);   //Move the n-2 plates above from C to B with the help of A
}

Deformation question 2 (change conditions):

If A and B cannot move directly, how to solve it?

Idea: since you can't move directly between A and B, you need to use C to move from A to B, or from B to A, first to C, and then to A or B

Steps:

1. First n - 1 Pass C Move to B upper 
2. Move the bottom to C upper
3. Pass again C hold B Upper n-1 Move to A upper
4. Move the bottom to B upper
5. Finally n - 1 Pass C Move to B upper

The number of times required to move n plates = the number of times to move n-1 plates to B through C + the number of times to move the bottom to C + the number of times to move n-1 plates to A again through C + the number of times to move the bottom plate to B + the number of times to move n-1 plates back to B through C

Therefore, there are still two solutions:

Solution 1 (mathematical method):

//In order to distinguish, it is changed here to G(n)
G( n ) = G( n - 1 ) + 1 + G( n - 1 ) + 1 + G( n - 1 )
// Similarly, the mathematical derivation process is omitted this time. The proof idea is the same as the first one. If you are interested, you can contact the author
       = 3^n - 1

Solution 2 (recursive method):

unsigned int count = 0;
void hanio(int n,char A,char B,char C){
    
	if(n == 1 ){
	   cout<<"Put "<<n<<" from "<<A<<" to "<<B<<endl;// If there is only one, put this plate on C first
       cout<<"Put "<<n<<" from "<<C<<" to "<<B<<endl;// Put this plate on B
       count += 2;
    }
	else
	{
	   hanio(n-1,A,B,C);  								 //Move n-1 from C to B 
	   cout<<"Put "<<n<<" from "<<A<<" to "<<C<<endl;	//Move the bottom to C
       count += 1;
       hanio(n-1,B,A,C);								//Then move n-1 on B to A through C
       cout<<"Put "<<n<<" from "<<C<<" to "<<B<<endl;	//Move the bottom to B
       count += 1;        
	   hanio(n-2,A,B,C);  								 //Finally, move n-1 to B through C
}

Welcome to scan the code and pay attention to me. There are more high-quality original articles!

Posted by markbm on Thu, 18 Nov 2021 16:29:50 -0800