Understand the algorithm in seconds | Tower of Hanoi problem and stick triangle

picture

In mathematics and computer science, recursion refers to a method in which a procedure or function calls itself directly or indirectly in its definition or description. It usually converts a large and complex problem layer by layer into a smaller-scale problem similar to the original problem to solve. The recursive strategy only needs a small number of programs to describe the multiple repeated calculations required in the problem-solving process, which greatly reduces the amount of code in the program. The power of recursion lies in defining infinite collections of objects with finite statements. A recursive problem can be divided into two stages: recursion and regression. In the recursive stage, the solution of the more complex problem (scale n) is pushed to the solution of the simpler problem (scale smaller than n); in the regression stage, when the solution of the simplest case is obtained, it returns step by step, The solutions to slightly more complex problems are obtained in turn.

Only problems that satisfy the following three conditions at the same time can be solved recursively.

(1) A problem can be transformed into a smaller sub-problem similar to the original problem to solve. For example, in the calculation of the factorial of n, the problem of the factorial of n is transformed into the factorial of n-1 multiplied by n, and this problem can be solved.

(2) This problem is exactly the same as the sub-problem after decomposition, except that the data scale is different. For example, in the factorial problem of n, the idea of ​​solving the factorial of n is exactly the same as the idea of ​​solving the factorial of n-1.

(3) There is a recursive termination condition.

Decompose the problem into sub-problems, and then decompose the sub-problems into sub-sub-problems, and decompose layer by layer. There cannot be an infinite loop, which requires a termination condition. For example, in the factorial problem of n, the factorial of 0 or 1 is 1, that is, f(1)=1, f(0)=1, which is the termination condition of recursion.

Recursion is the basis of many algorithms, and it is an important idea and mechanism in programming, such as divide and conquer, depth-first search, dynamic programming and other algorithms that use recursive ideas.

01. Tower of Hanoi problem

The Tower of Hanoi problem is a classic example of using a recursive method to solve a problem.

Problem Description:

Tower of Hanoi is a puzzle game originated in India, also called Tower of Hanoi. According to legend, it originated from the three vajra pillars created by Brahma in Indian mythology. On one pillar, 64 gold discs from small to large are stacked up and down. Brahma ordered the Brahmins to move the disks to another pillar in ascending order, and the large disk could not be placed on the small disk. When these 64 discs are moved, the world will be destroyed.

So, many people will ask how much time it will take for 64 discs to move? Ancient India is very far away from now, haven't the 64 discs moved yet? How much time do we need to calculate to complete this task? The calculation result is very scary. The number of times to move the disk is 2n-1, that is, 18446744073709551615. Assuming that it takes one second to move the disk once, a year is 31536000 seconds. Then, 18446744073709551615/31536000 is approximately equal to 584942417355 years, which is about 585 billion years. The current life of the sun is about 5 billion years, and the full life of the sun is about 10 billion years. Therefore, the entire human civilization cannot wait for the day of moving the complete disc. Many people have become interested in the solution of the Tower of Hanoi. Do they have regular algorithms from the first-order Tower of Hanoi to the N-order Tower of Hanoi? Can you program how to output each move? That's what this example addresses.

enter:

Enter a positive integer n, indicating that there are n discs on the first column.

output:

Output a sequence of operations in the format move t from x to y. One row for each operation means moving the disc numbered t on the x column to the column y. The columns are numbered a, b, and c. It is necessary to transfer all the plates from the a column to the c column with the least operations.

Input sample:

3

Sample output:

move 1 from a to c
move 2 from a to b
move 1 from c to b
move 3 from a to c
move 1 from b to a
move 2 from b to c
move 1 from a to c

Problem-solving ideas:

The implementation of this algorithm can be simply divided into the following three steps.

(1) Move the n-1th disk from a to b.

(2) Move the nth disc from a to c.

(3) Move the n-1th disc from b to c.

Starting from here, coupled with the analysis of the solution to the above mathematical problem, it is not difficult to find that the number of moving steps must be an odd number of steps.

(1) The second step is to move the remaining plate on the a column to the c column.

(2) The first step can be regarded as moving the n-1 discs on the a pillar to the b pillar by means of the c pillar.

(3) The third step can be regarded as moving the n-1 discs on b to the c pillar by means of the a pillar.

For example, the movement of the 3rd-order Tower of Hanoi: A→C, A→B, C→B, A→C, B→A, B→C, A→C.

Reference program:

#include <fstream>
#include <iostream>
using namespace std;
/ *将x柱子上编号为 t的圆盘移动到 柱子上 * /
void Move(int t,char x,char y) [cout<<"move "<<t<<" from "<<x<<" to "<<y<<endl;
/*将 n个圆盘从 a 柱子借助 b 柱子移到 c 柱子 * /
void Hannoi(int n,char a,char b,char c)
{
  if(n==1)
move(1,a,c)
Move(1,a,c); /* 若只有一个圆盘,则直接将该圆盘由 a 柱子移到 c 柱子 * /
else
{
Hannoi(n-1,a,c,b); / * 把 a 柱子上的 n-1个圆盘借助 c 柱子移到 b 柱子上* /
Move(n,a,c);  /*把 a 柱子上剩下的一个盘子移到 c 柱子上*/
Hannoi(n-1,b,a,c);  /*把b 柱子上的 n-1个圆盘借助 a 柱子移到 c 柱子上* /
 
}
})


int main()
int n;
scanf("%d",&n);
Hannoi(n,'a','b','c') ;
return 0;
}

02. Wooden stick triangle

Problem Description:

Little A has many wooden sticks of different lengths at home. One day he was bored and played with these wooden sticks to relieve his boredom. Little A is good at mathematics, so he wants to pick three sticks to form a right triangle. Of course, there may be many ways to choose this. He also wants to pick three sticks to form a triangle with the largest area. right triangle.

enter:

There are multiple sets of input, each set of input includes two lines, the first line enters an n (0≤n≤100), indicating that the small A has n wooden sticks, and the next line has n integers (n≤1000), indicating the number of wooden sticks Length (lengths are given from smallest to largest).

output:

Output the area of ​​the right-angled triangle with the largest area, and keep 3 decimal places. If it cannot be formed, output "My Good!".

Input data:

4
1 2 3 4
5
2 3 4 5 6
6
3 4 5 6 8 10
2
1 1

Output Data:

My Good!
6.000
24.000
My Good!

Problem-solving ideas:

Seeing the title, it is easy to think that if you find the solution to all the situations in which three wooden sticks are selected from n wooden sticks, then the answer will come out.

The main problem now is how to enumerate all cases programmatically. We know that the hypotenuse is the longest among the three sides of a right triangle. The title gives a condition of "the length is given from small to large", so that we can enumerate the shortest, second longest and longest sides of the triangle in turn, The specific implementation code is as follows.

Reference program:

#include< stdio.h>
#include<stdlib.h>
int main()
{
int i,j,k;
double ans;
int n;
int len[110];
while(scanf(rd",&n)!=EOF)
{for(i = 1;i <= n;i++)scanf("%d",&len[i]); //存储木棒长度
ans = -1;
for(i = l;i <= n;i++){  //枚举最短木棒
for(j = i+l;j <= n;j++){ //枚举第二长的木棒
for(k = j+1;k <= n;k++){  //枚举最长的木棒
if(len[i]*len[i] + len[j]*len[j] == len[k]* len[k]){ //如果是直角三角形
if(0.5*len[i]*len[j] > ans) //取最优解
ans = 0.5*len[i]*len[j];
}
}
}
}

if(ans == -1)
printf("My Good! \n");
else
printf("%.3lf\n",ans);
}

Guess you like

Origin blog.csdn.net/qq_41640218/article/details/132354128