算法描述:主要难点在于找到递推方程式和边界函数。
举例说明,2个苹果放在8个盘子里面,有6个盘子都用不到。所以与只考虑2个盘子一样。
2个苹果放在2个盘子里,显然只有2种放法,1-1 或者 2-0。也就是只用两种,所有盘子全用上,和有n个盘子没用上。这就是这个算法设计的精妙之处了。
如何设计使得递归是能遍历到所有情况?
我暂时还没有完全理解,这位老师的方法是 k个盘子的情况 = 盘子数减一的情况 + 本次盘子数的情况。思来想去觉得十分精妙,恰好每一次计算了 规模小1的情况 和 本次规模(为k)的情况,而下一次规模小1的情况也恰好计算了 规模再小1的情况 和 本次规模(为k-1)的情况。
详细参考:程序设计与算法(二)算法基础_哔哩哔哩_bilibili
OJ题目描述
小明刚放学回家,老妈就吩咐他:马上有客人要来,赶快把苹果洗了放到盘子里去。小明要把 m 个同样的苹果放到 n 个同样的盘子里,允许有的盘子空着不放,有多少种不同的 分法。5,1,1 与 1,5,1 是同一种放法。
输入描述
多组输入,输入两个数 m 和 n 代表苹果数和盘子数,m 和 n 均不超过 20
输出描述
对于每一组数,有多少种不同的放法
样例输入
7 3
样例输出
8
按照此思路写的代码
#include<bits/stdc++.h>
using namespace std;
/*
7 3
*/
int f(int appleNum, int panNum) {
if (appleNum == 0)
return 1;
if (panNum == 0)
return 0;
if (appleNum < panNum)
return f(appleNum, appleNum);
if (appleNum >= panNum)
return f(appleNum, panNum - 1) + f(appleNum - panNum, panNum);
}
int main() {
int apple;
int pan;
while (cin>>apple>>pan)
{
cout << f(apple, pan) << endl;
}
return 0;
}