整数划分 递归实现(C++)
文章目录
一、什么是整数划分
所谓整数划分,是指把一个正整数n写成如下形式:
n=m1+m2+⋅⋅⋅+min=m_1+m_2+···+m_in=m1+m2+⋅⋅⋅+mi
其中mim_imi为正整数,并且1≤mi≤n1 \leq m_i \leq n1≤mi≤n,则{m1,m2,⋅⋅⋅,mim_1,m_2,···,m_im1,m2,⋅⋅⋅,mi}为n的一个划分。
如果{m1,m2,⋅⋅⋅,mim_1,m_2,···,m_im1,m2,⋅⋅⋅,mi}中的最大值不超过mmm,即max(m1,m2,…,mi)≤mmax(m_1,m_2,…,m_i) \leq mmax(m1,m2,…,mi)≤m,则称它属于n的一个m划分。
这里我们记n的m划分的个数为f(n,m)f(n,m)f(n,m);
例如:
当n=4时,它有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
注意4=1+3 和 4=3+1被认为是同一个划分。
该问题是求出nnn的所有划分个数,即f(n,m)f(n,m)f(n,m)。
二、递归算法实现
1. 设计递归方程
根据n和m的关系,考虑以下几种情况:
- 当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
- 当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,…,1};
- 当n=m时,根据划分中是否包含n,可以分为两种情况: 划分中包含n的情况,只有一个即{n};
- 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此f(n,n)=1+f(n,n−1)f(n,n) =1 + f(n,n-1)f(n,n)=1+f(n,n−1);
-
划分中包含m的情况,即{m, {x1,x2,⋅⋅⋅,xix_1,x_2,···,x_ix1,x2,⋅⋅⋅,xi}},其中{x1,x2,⋅⋅⋅,xix_1,x_2,···,x_ix1,x2,⋅⋅⋅,xi}的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分的个数为f(n−m,m)f(n-m, m)f(n−m,m);
因此f(n,m)=f(n−m,m)+f(n,m−1)f(n, m) = f(n-m, m)+f(n,m-1)f(n,m)=f(n−m,m)+f(n,m−1);
综上所述:
{f(n,m)=1n=1∣∣m=1f(n,n)n<m1+f(n,m−1)n=mf(n−m,m)+f(n,m−1)n>m \begin{cases} f(n, m)= 1 & n=1 || m=1 \\ f(n, n) & n<m \\ 1+ f(n, m-1) & n=m \\ f(n-m,m)+f(n,m-1) & n>m \end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧f(n,m)=1f(n,n)1+f(n,m−1)f(n−m,m)+f(n,m−1)n=1∣∣m=1n<mn=mn>m
——摘录自百度百科
2. 确定边界条件
根据递归方程,我们可以看出:
- m=1∣∣n=1m=1 || n=1m=1∣∣n=1属于回归条件;
- n<mn<mn<m会转化为n=mn=mn=m,而n=mn=mn=m随着mmm- -会转换为n>mn>mn>m;最终达到回归条件。
3. 编写程序代码
此程序不仅计算了划分个数,而且输出打印了所有的划分形式(移除show()函数可移除此功能)。
注:show()应该函数有借鉴学习于一位博主,但是找不到这位大大了qaq。
// 整数划分的递归实现算法 #include <iostream> #include <string> using namespace std; int int_HuaFen(int n, int m); void show(int n, int m, string s); int main() { string s; // 用于展示所有整数划分形式 int n = 1; // 用于整数划分的整数 cout << "请输入一个正整数进行整数划分:"; cin >> n; cout << "全部划分为:" << endl; show(n, n, s); cout << "划分数为:" << int_HuaFen(n, n) << endl; return 0; } // 递归计算划分数 int int_HuaFen(int n, int m) { if (n == 1 || m == 1) return 1; else if (n < m) return int_HuaFen(n, n); else if (n == m) return 1 + int_HuaFen(n, n - 1); else return int_HuaFen(n, m - 1) + int_HuaFen(n - m, m); } // 递归展示所有划分形式 void show(int n, int m, string s) { if (n == 1 || m == 1) { for (int i = 0; i < n - 1; i++) s += string("1+"); cout << s << "1\n"; return; }else if (m > n) { return show(n, n, s); }else if (n == m) { cout << s << n << endl; return show(n, m - 1, s); } if (n - m != 0) show(n - m, m, s + to_string(m) + string("+")); else cout << s << m << endl; show(n, m - 1, s); }
4. 运行结果展示
*其它一些常见算法请参阅此链接~
最后,非常欢迎大家来讨论指正哦!
- 递归实现放小球(整数划分)问题
- 整数划分的递归实现算法
- Ackerman函数的递归、全排列的递归实现、整数划分的递归、二分搜索的递归、合并排序的递归、.快速排序
- 小范围求整数的划分(递归实现)
- 递归:整数划分的java编程实现
- 整数划分的递归实现算法
- 算法设计与分析 整数划分的递归实现算法
- 递归实现整数划分
- 求n的阶乘(递归&&非递归),Fibonacci函数,二分法查找,汉诺塔实现,排列组合,整数划分,一元多项式的加减乘
- 整数划分问题算法分析与实现(递归)
- 整数划分 用递归,动态规划,母函数法实现
- 实验一 分治与递归―整数划分 java实现
- 整数划分问题 Java简单实现
- 整数的划分(变形)(分治递归)
- C语言递归方式实现打印一个整数的每一位
- 整数划分(C语言实现)
- 已知函数t(n)=2*t(n/2)+n,其中t(0)=0,n为整数,用递归和非递归实现(栈实现)
- 递归 —— 整数划分(包括输出划分的具体情况)
- 递归 002:简单的整数划分问题
- 计算整数的划分数(递归)