描述
把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?
注意:如果有7个苹果和3个盘子,(5,1,1)和(1,5,1)被视为是同一种分法。
数据范围:0≤m≤10 0≤m≤10 ,1≤n≤10 1≤n≤10 。
输入描述:
输入两个int整数
输出描述:
输出结果,int型
示例1
输入:
7 3
输出:
8
理解
注意苹果和盘子均是无序的,因此将求解该问题理解为求解满足下列条件的数列数量:
① 长度为n(盘子数)
② 和为m(苹果数)
③ 不严格递减(无序性)
求解该问题,有两种思路:
方案1:递归
固定数组第一项的数,求剩余部分满足条件的数列的数量,代码:
# 苹果和盘都是无序的
# 不递增数列的数量
def getNonIncreaseListNum(head_cap,sum,size):
if(sum < 0): return 0
if(head_cap*size<sum): return 0
if(sum == 0): return 1
if(size == 1): return 1
list_num = 0
for head_fig in range(head_cap,-1,-1):
list_num += getNonIncreaseListNum(head_fig,sum-head_fig,size-1)
return list_num
input_str = input()
m,n = list(map(int,input_str.split()))
way_num = getNonIncreaseListNum(m,m,n)
print(way_num)
方案2:动态规划
假设数列和为i,数列长度为j,满足条件的数列数量为dp[i][j],那么,
当i<j时,由于数列递增,那么必定数列的后(j-i)项为0,因此
当i<j,dp[i][j] = dp[i][i]
否则当i≥j时,有两种情况:数列最后一项是否为0。
当数列最后一项为0时,此时满足条件的数列数量为:dp[i][j-1]
当数列最后一项不为0时,若将数列每一项减1,等价于满足数列和为i-j的数列和数量,因此
当i≥j时,dp[i][j] = dp[i][j-1] + dp[i-j][j]
特别的,dp[0][j]=1,dp[1][j] = 1,dp[i][1] = 1
代码:
# 苹果和盘都是无序的
# 不递增数列的数量
input_str = input()
m,n = list(map(int,input_str.split()))
dp = [[1]*(n+1)]
dp.append([1]*(n+1))
for i in range(2,m+1):
dp.append([1]*(n+1))
for j in range(2,n+1):
if(i<j):
dp[i][j] = dp[i][i]
else:
dp[i][j] = dp[i-j][j] + dp[i][j-1]
print(dp[m][n])