简单整数划分(递归法+动态规划法)

整数划分:

所谓整数划分,就是将一个数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;
}







  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值