递归算法实例应用(一)
递归简笔
递归和普通函数调用一样,都是通过函数栈实现。
以斐波那契数列递归调用为例
递归时函数调用栈的进栈、出栈过程可以由上述图示直观的体现出来,
因此可以得出递归的几个作用:
1)替代多重循环
2)解决以递归形式或潜在以递归形式定义的问题
3)将问题规模分解,分解为规模更小的子问题进行求解
⋯ ⋯ ⋯ \cdots\cdots\cdots ⋯⋯⋯
Hanoi (Simple)
Description
古代有一座汉诺塔,塔内有3个座A、B、C,A座上有n个盘子,盘子大小不等,大的在下,小的在上,如图4-1所示。有一个和尚想把这n个盘子从A座移到C座,但每次只能移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座来放盘子。要求输出移动的步骤。
Input
汉诺塔内的盘子个数 n ( 1 ≤ n ≤ 64 ) n(1 \le n \le 64) n(1≤n≤64)。
Output
输出移动的步骤,每行一步,如从A座移动到C座,输出“A->C”。
Sample Input
3
Sample Output
A->C
A->B
C->B
A->C
B->A
B->C
A->C
这是最简单的Hanoi问题,其余进阶版的Hanoi问题均由此发展而来。
该题是一个非常明显的以递归形式定义的问题,即:
要把A座上的盘子移动到C座的问题分解为三步:
- 把A座上的n-1个盘子移动到B座作为中转,且以C座作为中转;
- 把A座剩余的一个盘子移动到C座;
- 再把B座的n-1个盘子移动到C座,且以A做作为中转。
这样就把原问题的规模减小至n-1,通过逐层递归可以将问题规模减少至1,此时就可以通过直接将A座盘子移动到C座完成,在逐步向上返回至上一层调用函数,直至问题规模n完成求解。
由上述分析显然可知,当问题规模减少至1时为终止条件,此时应将A座盘子移动到C座上,即输出A->C,同时结束本次递归,返回至上一层递归函数处。
所以主函数及递归段代码为:
void Hanoi(int n, char A, char B, char C) {
if (n == 1) {
//问题规模到达1时为递归终止条件
printf("%c->%c\n", A, C);
return;
}
//将A座n-1个盘子移动至B座,同时以C座作为中转
Hanoi(n - 1, A, C, B);
//将A座第n个盘子移动至C座
printf("%c->%c\n", A, C);
//将B座的n-1个盘子移动至C座,同时以A座作为中转
Hanoi(n - 1, B, A, C);
}
int main() {
int n;
scanf("%d",&n);
//将n层汉诺塔中A座移动到C座,同时以B座作为中转
Hanoi(n, 'A', 'B', 'C');
}
N Queens
Description
The eight queens puzzle is the problem of putting eight chess queens on an 8 × 8 chessboard such that none of them is able to capture any other. The puzzle has been generalized to arbitrary n × n boards. Given n, you are to find a solution to the n queens puzzle.