版本一:60%,数据大了会超时
def backtracking(path,n,k,startindex,total):
if len(path) == k:
if sum(path) == n:
total[0] += 1
return
for i in range(startindex,n):
if sum(path)+i > n :#剪枝
break
path.append(i)
backtracking(path,n,k,i,total)
path.pop()
if __name__ == "__main__":
n, k = map(int,input().split())
total = [0]
path = []
backtracking(path,n,k,1,total)
print(total[0])
版本二:感觉已经没什么好优化的了但是还是超时。
def backtracking(path,n,k,startindex,total,sum_path):
if len(path) == k:
if sum_path == n:
total[0] += 1
return
for i in range(startindex,n):
new_sum = sum_path + i
if new_sum > n :
break
path.append(i)
backtracking(path,n,k,i,total,new_sum)#整数为不可变数据类型,回溯后会回到他在父级递归中的值
path.pop()
if __name__ == "__main__":
n, k = map(int,input().split())
total = [0]
path = []
backtracking(path,n,k,1,total,0)
print(total[0])
版本三:用动态规划做,ac
行号为i(格子数),列号为j(待分总数)
当 i =1 或者 i=j 或者 i+1=j 时,取法为1种
对于其他:可以分为两种情况取1和不取1,这两种情况合起来就是将总数j分配给i个格子的所有取法。
取1:先把1个格子里填入1,剩余的总数和格子数需要各减一,此时取法等于j-1和i-1时的取法即 = dp[i-1][j-1]
不取1:每个格子至少取2,先往每个格子里分配一个1进去,总数还剩下 j-i ,此时取法等于在i个格子对j-i进行分配即 = dp[i][j-i]
n, k = map(int,input().split())
rem = [[0 for i in range(n)]for i in range(k)]
rem[0] = [1 for i in range(n)]
for i in range(1,k):
for j in range(i,n):
if i == j or j == i+1:
rem[i][j] = 1
else:
rem[i][j] = rem[i-1][j-1]+rem[i][j-i-1]
print(rem[k-1][n-1])