关于递归的几个知识:
递归的三个要点:
1.递归式:如何将原问题划分成子问题
2.递归出口:递归终止条件,即最小子问题的求解,可以允许多个出口
3.界函数:问题规模变化的函数,它保证递归的规模向出口条件靠拢
递归解决问题的关键:
1)找出递推公式
2)找到递归终止条件
注意事项:由于函数的局部变量是存在栈上的,如果有体积大的局部变量,比如数组,而递归层次又可能在很深的情况下,也许会导致栈溢出,因此可以考虑使用全局数组或动态分配数组
问题:m个苹果,n个盘子,问多少种不同方法?盘子和苹果是没有编号的,即1,2,3和3,2,1算是一种放法
算法:1.当n > m:必定有n - m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响即if(n > m) f(m,m) = f(m,m)
当n <= m:不同的 放法分成两类:
a.有至少一个盘子空着,即相当于f(m,n) = f(m, n - 1)
b.所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同方法的数目,即
f(m, n) =f(m - n, n)
而总的放苹果的放法数目等于两者的和,即f(m,n) = f(m, n - 1) + f(m - n,n)
出口调价说明:
a.当n = 1时,所有苹果必须放在一个盘子里,所以返回1
b.当没有苹果可放时,定义为1中放法,所以返回1
c.递归的两条路,第一条n会逐渐减少,终会到达出口n == 1;第二条m会逐渐减少
,因为n > m时,会返回f(m, m),所以终会到达出口m == 0.
#include <iostream>
using namespace std;
int f(int m, int n)
{
if(n == 1 || m == 0)
return 1;
if(m < n)
{
return f(m, m);
}else
{
return f(m, n -1) + f(m - n, n);
}
}
int main()
{
int m;
int n;
cin >> m;
cin >> n;
cout << "The apple is: " << m << endl;
cout << "The dish is: " << n <<endl;
int result = f(m, n);
cout << "The way to put apple is: " << endl;
cout << result << endl;
return 0;
}