您的位置:首页 > 编程语言 > C语言/C++

整数划分 递归实现(C++)

2020-06-01 05:12 531 查看

文章目录

一、什么是整数划分

所谓整数划分,是指把一个正整数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的关系,考虑以下几种情况:

  1. 当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
  2. 当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,…,1};
  3. 当n=m时,根据划分中是否包含n,可以分为两种情况: 划分中包含n的情况,只有一个即{n};
  4. 划分中不包含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, {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);
    1. 划分中不包含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)=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. 运行结果展示

    *其它一些常见算法请参阅此链接~

    最后,非常欢迎大家来讨论指正哦!

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: