题目链接: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、这道题跟装盘子那道差不多了 ,都是要分子情况