洛谷 P1025 [NOIP 2001 提高组] 数的划分 Python

版本一: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])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值