day37 第九章 动态规划 part05

tips:

1.两层for可以理解为是按顺序的。外层物品内层背包,不同物品放进背包只有一种顺序,如a,b,放时要么a在前,要么b在前,只有一种之前定好的物品的顺序;外层背包内层物品,a,b可以有a+b和b+a两种,均计入。
引申:
排列,ab,ba算两种排列方式
组合,ab,ba算一种排列方式,如果只有ab,那也是组合数

2.写算法不需要证明,找例子就行

完全背包

n, bagweight = map(int, input().split())
weights = [0,]
values = [0,]
for i in range(n):
    weight, value = map(int, input().split())
    weights.append(weight)
    values.append(value)

#二维
#初始化dp[0][..] = 0/dp[..][0] = 0
# dp = [[0]*(bagweight+1) for _ in range(n+1)]

# for i in range(1, n+1):
#     for j in range(bagweight+1):
#         if j

518. 零钱兑换 II

种类问题

二维

dp[i][j]  = d[i-1][j] + dp[i][j-coins[i]] 目标和为j的种类是没有i的种类数+有i的种类数

for的物品和容量能交换, 都表示组合数,因为dp[i-1][j]不变,加入顺序不变

一维

dp[j] = dp[j] + dp[j-coins[i]] 

for外层物品,内层容量,表示组合数(种类),因为遍历时物品加入的顺序不变

for外层容量,内层物品,表示排列数,因为遍历时加入顺序不同算2遍,3=2+1第一行/1+2第二行,但不要按照二维来想(实际上,按二维解释,dp[i][j] = dp[i-1][j] + dp[all items][j-coins[i]])

class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        l = len(coins)

        # #二维
        # dp = [[0] * (amount+1) for _ in range(l)]
        # for i in range(l):
        #     dp[i][0] = 1
        
        # for i in range(0, l):
        #     for j in range(0, amount+1):
        #         if j

377. 组合总和 Ⅳ

排列:外层背包,内层物品

class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:
        l = len(nums)

        # initialization
        dp = [0] * (target+1)
        dp[0] = 1

        for j in range(1, target+1):
            for i in range(l):
                if j>=nums[i]:
                    dp[j] += dp[j-nums[i]]

        return dp[-1]

70. 爬楼梯 (进阶)

爬楼梯思想:

1.dp数组及其含义:

dp[i]表示爬到楼层i有几种方法

2.状态转移公式:

dp[i] = dp[i-1]+dp[i-2]+...+dp[i-m]

爬一步+爬两步+...+爬m步(注意最多i=m)

3.初始化:

dp[0]=1

由dp[1]=1,dp[2]=2推出,没什么特别的意义

4.遍历顺序:

外层总楼梯数,内层一次爬几步

完全背包思想:

物品1,2,..,m,要装进容量为n的背包里,每种物品有无限个,求有多少种方法(先后顺序算不同方法)

1.dp数组及其含义

dp[j]表示装满容量为j的背包,有多少种方法

2.状态转移公式

dp[j] += dp[j-i]

没有装i+装了i

3.初始化

dp[0]=1

啥也不装也是一种方法?应该还是从dp[1]=1推导的

4.遍历顺序

求排列数,先背包,再物品

n,m = map(int, input().split())

#initialization
dp = [0] * (n+1)
dp[0] = 1

# 完全背包
# for j in range(n+1):
#     for i in range(1, m+1):
#         if j>=i:
#             dp[j] += dp[j-i]
            
# print(dp[-1])

# 爬楼梯
dp = [0]*(n+1)
dp[0] = 1

for i in range(1,n+1):
    for j in range(1,m+1):
        if j<=i:
            dp[i] += dp[i-j]
        
print(dp[-1])
        

你可能感兴趣的:(动态规划,算法)