[背包问题汇总] 01背包、完全背包dp

 总结一下见到的各种背包问题,先将题目列举出来,有机会了放题解~

01背包

416. 分割等和子集

474. 一和零

494. 目标和

879. 盈利计划

1049. 最后一块石头的重量 II

​​​​​​1230. 抛掷硬币w

有一些不规则的硬币。在这些硬币中,prob[i] 表示第 i 枚硬币正面朝上的概率。

请对每一枚硬币抛掷 一次,然后返回正面朝上的硬币数等于 target 的概率。

示例 1:

输入:prob = [0.4], target = 1
输出:0.40000


示例 2:

输入:prob = [0.5,0.5,0.5,0.5,0.5], target = 0
输出:0.03125 

提示:

1 <= prob.length <= 1000
0 <= prob[i] <= 1
0 <= target <= prob.length
如果答案与标准答案的误差在 10^-5 内,则被视为正确答案。

# 这段代码中,dp[i][j]表示前i枚硬币投掷后正面朝上的硬币数等于j的概率。
# 根据状态转移方程,我们可以更新dp[i][j]的值。
# 外层循环遍历每个硬币,内层循环遍历目标值。
class Solution:
    def probabilityOfHeads(self, prob, target):
        n = len(prob)
        dp = [[0.0] * (target + 1) for _ in range(n + 1)]
        dp[0][0] = 1.0  # 初始时没有硬币,正面朝上的概率为1

        for i in range(1, n + 1):
            for j in range(target + 1):
                dp[i][j] = dp[i - 1][j] * (1 - prob[i - 1])  # 不选第i枚硬币的情况
                if j > 0:
                    dp[i][j] += dp[i - 1][j - 1] * prob[i - 1]  # 选第i枚硬币的情况

        return dp[n][target]

# 示例
sol = Solution()
prob = [0.4, 0.6, 0.3]
target = 3
result = sol.probabilityOfHeads(prob, target)
print(result)


# 这段代码中,我们使用dp数组来记录每个目标值出现的概率。
# 外层循环遍历每个硬币,内层循环从后往前更新dp数组,确保更新时不会影响前面的值。
# 最终,dp[target]即为正面朝上的硬币数等于target的概率。
class Solution:
    def probabilityOfHeads(self, prob, target):
        n = len(prob)
        dp = [0.0] * (target + 1)
        dp[0] = 1.0  # 初始时没有硬币,正面朝上的概率为1

        for i in range(1, n + 1):
            # 从后往前更新,避免覆盖前面的值
            for j in range(min(target, i), -1, -1):
                dp[j] = dp[j] * (1 - prob[i - 1])  # 不选第i枚硬币的情况
                if j > 0:
                    dp[j] += dp[j - 1] * prob[i - 1]  # 选第i枚硬币的情况

        return dp[target]

# 示例
sol = Solution()
prob = [0.4, 0.6, 0.3]
target = 3
result = sol.probabilityOfHeads(prob, target)
print(result)

完全背包


1449. 数位成本和为目标值的最大数字

322. 零钱兑换

518. 零钱兑换 II

279. 完全平方数

139. 单词拆分

377. 组合总和 Ⅳ

待续……

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值