总结一下见到的各种背包问题,先将题目列举出来,有机会了放题解~
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. 组合总和 Ⅳ
待续……