整数划分:

所谓整数划分,就是将一个数n写成正整数相加的形式,如3可以划分为1+1+1,1+2,3等三种情况,而f(n,m)则表示,划分数中最大的数小于m时n的划分。如f(3,2)就是1+1+1,1+2两种。


递归法:

根据n和m的情况,有如下几种情况

1.当n == 1或m == 1时,都只有一种划分,其中n==1时,只有一种划分{1},只有m == 1时,只有一种划分{1,1,1…..,1};即n个1。

2.由于划分中没有负数,所以当n < 1或m < 1时,都只有0种划分。

3.当n < m时,由于没有负数,所以f(n,m)就相当于f(n,n);

4.当n == m时,可以分为两种情况:

(1).划分中有n即只有{n}一种情况。

(2).划分中没有n即划分中最大值小于等于n-1,即n对于n-1的所有划分。

所以综上,n == m时,f(n,n) == f(n,n-1)+1;

5.当n > m时,可以分为两种情况:

(1).划分中包含最大值m的情况,即{m,{x1,x2…..}},而在{x1,x2…..},也就是n-m中同样可能大于m,所以为n-m对于m的划分,即f(n-m,m);

(2).划分中不包含m,同情况4,所有值比m小,即f(n,m-1);

综上,f(n-m,m)+f(n,m-1)。


代码如下:

#include <bits/stdc++.h>
using namespace std;
int query(int n,int m)
{
    if(n == 1||m == 1)  return 1;
    if(n < 1||m < 1)    return 0;
    if(n < m)   return query(n,n);
    if(n == m)  return query(n,m-1)+1;
    if(n > m)   return query(n-m,m)+query(n,m-1);
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        cout<<"递归:"<<query(n,n)<<endl;
    }
    return 0;
}

动态规划法:

在递归法中的1,2情况都可以直接通过初始化dp数组来进行处理,而情况3,4,5则转换成动态转移方程就可以了。

转移方程:dp[n][m] += dp[i][j-1]+dp[i-j][j];

(当i-j < j时)dp[n][m] += dp[i][j-1]+dp[i-j][i-j];

#include <bits/stdc++.h>
using namespace std;
const int N = 100;
int main()
{
    int n;
    int dp[550][550];
    dp[1][1] = 1;
    for(int i = 2;i <= N; i++){dp[i][1] = 1;dp[i][i] = 1;}

    for(int i = 2;i <= N; i++)
    {
        for(int j = 2;j <= i; j++)
        {
            if(i-j < j) dp[i][j] += dp[i][j-1]+dp[i-j][i-j];
            else dp[i][j] += dp[i][j-1]+dp[i-j][j];
        }
    }
    while(~scanf("%d",&n))
        cout<<"dp:"<<dp[n][n]<<endl;
    return 0;
}







版权声明:本文为acmer_mozhu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/acmer_mozhu/article/details/79502435