【递归】整数划分(C++)
文章目录一、什么是整数划分二、递归算法实现1. 设计递归方程2. 确定边界条件3. 编写程序代码4. 运行结果展示一、什么是整数划分所谓整数划分,是指把一个正整数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
一、什么是整数划分
-
所谓整数划分,是指把一个正整数n写成如下形式: n = m 1 + m 2 + ⋅ ⋅ ⋅ + m i n=m_1+m_2+···+m_i n=m1+m2+⋅⋅⋅+mi;
其中 m i m_i mi为正整数,并且 1 ≤ m i ≤ n 1 \leq m_i \leq n 1≤mi≤n,则 { m 1 , m 2 , ⋅ ⋅ ⋅ , m i } \{m_1,m_2,···,m_i\} {m1,m2,⋅⋅⋅,mi}为n的一个划分。 -
如果 { m 1 , m 2 , ⋅ ⋅ ⋅ , m i } \{m_1,m_2,···,m_i\} {m1,m2,⋅⋅⋅,mi}中的最大值不超过m,即 m a x ( m 1 , m 2 , … , m i ) ≤ m max(m_1,m_2,…,m_i) \leq m max(m1,m2,…,mi)≤m,则称它属于n的一个m划分。
-
例如:当n=4时,它有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
注意4=1+3和4=3+1被认为是同一个划分。 -
整数划分问题就是求出 n 的所有划分个数。
二、递归算法实现
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)。
- 当n<m时,由于划分中不可能出现负数,因此就相当于 f ( n , n ) f(n,n) f(n,n);
- 当n>m时,根据划分中是否包含最大值m,可以分为两种情况:
- 划分中包含m的情况,即 { m , { x 1 , x 2 , ⋅ ⋅ ⋅ , x i } } \{m,\{x_1,x_2,···,x_i\}\} {m,{x1,x2,⋅⋅⋅,xi}},其中 { x 1 , x 2 , ⋅ ⋅ ⋅ , x i } \{x_1,x_2,···,x_i\} {x1,x2,⋅⋅⋅,xi}的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分的个数为 f ( n − m , m ) f(n-m, m) f(n−m,m);
- 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为 f ( n , m − 1 ) f(n,m-1) 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)=f(n−m,m)+f(n,m−1)。
综上所述:
{
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
\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. 编写程序代码
此程序不仅计算了划分个数,而且输出打印了所有的划分形式(移除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);
}
3. 运行结果展示
三、友情链接~
- 其它一些常见算法请参阅此链接~
最后,非常欢迎大家来讨论指正哦!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)