整数划分——经典dp

来源:互联网 发布:用c语言打开文件 编辑:程序博客网 时间:2024/06/05 10:40

题目:

给两个整数n和k,分别计算一下情况的数目。(1 <= n <= 50, 1 <= k <= n)

1、将n划分成若干正整数之和的划分数。
2、将n划分成k个正整数之和的划分数。
3、将n划分成最大数不超过k的划分数。
4、将n划分成若干个奇正整数之和的划分数。
5、将n划分成若干不同整数之和的划分数。


一、将n划分成若干正整数之和的划分数。

这种情况没说划分的整数不能相同,例如5 = 2+2+1,可以划分出两个2来。

用dp[i][j]表示将i划分为最大数不超过j的划分数:

1、当i<j时,因为j不可能大于i,所以dp[i][j] = dp[i][i]。

2、当i>j时,根据划分中有没有j分为两种情况:如果有j那么dp[i][j] = dp[i-j][j],即去掉这个j剩余其他数的划分;如果没有j,那么  dp[i][j] = dp[i][j-1],即i划分为不超过j-1的划分数。综合dp[i][j] = dp[i-j][j] +dp[i][j-1]。

3、当i=j时,还是根据划分中有没有j分为两种情况:如果有j,那么只有1中划分;如果没有j,dp[i][j] = dp[i][j-1]。综合dp[i][j] = 1+dp[i][j-1]。

最后dp[n][n]表示将n划分成不超过n的划分数,即结果。


二、将n划分成k个正整数之和的划分数。

用dp[i][j]表示将i划分为j个整数的划分数:

1、当i<j时,不可能存在,所以dp[i][j] = 0。

2、当i>j时,根据划分的数数有没有1这个数字分为两种情况:如果含有1,那么dp[i][j] = dp[i-1][j-1],即把这个1拿出来,将剩下的i-1划分为j-1份;如果不含有1,那么dp[i][j] = dp[i-j][j],即从每一份中拿出一个1,总数就变成了i-j但划分数目不变。综合为:dp[i][j] = dp[i-1][j-1] + dp[i-j][j]。

最后dp[n][k]就是结果。

3、当i=j时,这时只有一种划分,即每份都是1,dp[i][j] = 1。


三、将n划分成最大数不超过k的划分数。

这种情况与第一种情况的解法相同,dp[n][k]就是最后结果。


四、将n划分成若干个奇正整数之和的划分数。

用p[i][j]表示将i划分为j个奇数的划分数,用q[i][j]表示将i划分为j个偶数的划分数。

1、偶数的划分数可以由奇数来或得,即划分后的每个偶数都减去1,就变成了奇数,所以q[i][j] = p[i-j][j]

2、奇数的划分根据有没有1分为两种情况:如果含有1,那么p[i][j] = p[i-1][j-1],即拿去这个1,将剩下的i-1划分为j-1份;如果不含有1,那么每份都减去1,就变成了偶数,p[i][j] = q[i-j][j]。综合p[i][j] = p[i-1][j-1] + q[i-j][j]。

最后结果为:p[n][0]+p[n][1]+……+p[n][n]。


五、将n划分成若干不同整数之和的划分数。

与第一种情况有些相似,但是划分中不能有相同的数。(下面红色标记是与第一种情况的不同之处)

用dp[i][j]表示将i划分为不超过j的不同数的划分数:

1、当i<j时,因为j不可能大于i,所以dp[i][j] = dp[i][i]。

2、当i>j时,根据划分中有没有j分为两种情况:如果有j那么dp[i][j] = dp[i-j][j-1],即去掉这个j剩余其他数的划分,其余划分中最大数为j-1;如果没有j,那么  dp[i][j] = dp[i][j-1],即i划分为不超过j-1的划分数。综合dp[i][j] = dp[i-j][j-1] +dp[i][j-1]。

3、当i=j时,还是根据划分中有没有j分为两种情况:如果有j,那么只有1中划分;如果没有j,dp[i][j] = dp[i][j-1]。综合dp[i][j] = 1+dp[i][j-1]。

最后dp[n][n]就是结果。

这种情况还可以用另一种方法,类似于第二种情况:

用dp[i][j]表示为将i划分为j个不同的数,

1、当i<j时,不可能存在,dp[i][j] = 0。

2、当i=j时,由于划分的数都不能相同,所以也不存在,dp[i][j] = 0。

3、当i>j时,根据有没有1分为两种情况:如果含有1,那么每份都去掉1后就是将i-j划分为j-1个不同的数,dp[i][j]=dp[i-j][j-1];如果不含有1,那么每份都去掉1后就是将i-j划分为j个不同的数,dp[i][j] = dp[i-j][j]。综合dp[i][j] = dp[i-j][j-1]+dp[i-j][j]。

最后结果为dp[n][1]+dp[n][2]+……+dp[n][n]。


以上仅仅是思路,没有代码。如果有错误,请帮忙指出,谢谢。

原创粉丝点击