【DP_动态规划】整数划分

题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=90

整数划分

时间限制:3000 ms  |  内存限制:65535 KB

难度:3

输入

第一行是测试数据的数目M(1<=M<=10)。以下每行均包含一个整数n(1<=n<=10)。

输出

输出每组测试数据有多少种分法。

描述

将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 
其中n1≥n2≥…≥nk≥1,k≥1。 
正整数n的这种表示称为正整数n的划分。求正整数n的不 
同划分个数。 
例如正整数6有如下11种不同的划分: 
6; 
5+1; 
4+2,4+1+1; 
3+3,3+2+1,3+1+1+1; 
2+2+2,2+2+1+1,2+1+1+1+1; 
1+1+1+1+1+1。 


#include <iostream>

using namespace std;

int cnt,n;
int memo[11][11];

void init();
int dp(int n, int m);

int main()
{
    cin>>cnt;
    while(cnt--)
    {
        cin>>n;
        init();
        cout<<dp(n, n)<<endl;
    }
    return 0;
}

void init()
{
    for(int i=0; i<=n; i++)
    {
        for(int j=0; j<=n; j++)
        {
            memo[i][j]=0;
        }
    }
}
int dp(int n, int m)
{
    if(memo[n][m])
    {
        return memo[n][m];
    }
    else if(n==1||m==1)
    {
        memo[n][m]=1;
        return memo[n][m];
    }
    else if(m>n)
    {
        memo[n][m]=dp(n, n);
        return memo[n][m];
    }
    else if(m==n)
    {
        memo[n][m]=1+dp(n, m-1);
        return memo[n][m];
    }
    else
    {
        memo[n][m]=dp(n-m, m)+dp(n, m-1);
        return memo[n][m];
    }
}

【2018/11/8后记】

1.本题用了动态规划法+备忘录法,递归公式如下:

其中q(n,m)代表:要划分的整数为n,最大的加数<=m

如:q(3,2)代表:将3进行划分,最大的加数不能超过2,因此只有2+1,1+1+1这两种分法,因此q(3,2)=2

n和m的值有以下几种情况:

第一种情况:当n==1时,即要划分的整数为1,自然只有一种分法;当m==1时,n只能被划分成n个1相加,也只有一种分法

第二种情况:当n<m时,即要划分的整数为n,加数<=m。又因为加数<=n&&n<m,所以q(n,m)=q(n,n)

第三种情况:当n=m时,我们可以将其分成两种子情况:

①子情况:让最大的加数=m,那么分法只有1种:n=m

②子情况:让最大的加数<=m-1,那么问题转换成q(n,m-1),因为m=n,所以q(n,m-1)=q(n,n-1)

所以,第三种情况的分法q(n,m)=1+q(n,n-1)

第四种情况:当n>m时,我们可以将其分成两种子情况:

①子情况:让最大的加数=m,那么问题转换成q(n-m,m)

②子情况:让最大的加数<m,那么问题转换成q(n,m-1)

所以,第四种情况的分法q(n,m)=q(n-m,m)+q(n,m-1)

详细讲解请转这篇博客:https://blog.csdn.net/qq_41333482/article/details/82823742 

2、这道题跟装盘子那道差不多了 ,都是要分子情况

猜你喜欢

转载自blog.csdn.net/qq_41727666/article/details/83867107