【Day30】卡码网:46. 携带研究材料,LeetCode:416. 分割等和子集

文章目录

卡码网:46. 携带研究材料

https://kamacoder.com/problempage.php?pid=1046

0-1背包问题,二维

思路

  1. 定义:dp[i][j] 表示只考虑前 i 件物品(索引从 0 到 i ),在背包容量为 j 时能获得的最大价值。最终目标为 dp[n-1][bag]。
  2. 状态转移方程:
    (1)当 j < weight[i](当前容量放不下第 i 件物品)时:
    dp[i][j] = dp[i-1][j] ,即不选第 i 件,结果与前 i - 1 件相同。
    (2)当 j >= weight[i](可以放下第 i 件物品)时:
    dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])
    不选:价值为 dp[i-1][j] ;
    选:先腾出 weight[i] 的空间( j - weight[i] ),加上第 i 件的价值。
  3. 初始化:所有 dp[i][j] 初始化为0。

解答

python 复制代码
first_line = input().split()
n = int(first_line[0])
bag = int(first_line[1])

second_line = input().split()
third_line = input().split()
weight = [int(x) for x in second_line]
value = [int(x) for x in third_line]

dp = [[0] * (bag + 1) for _ in range(n)]

for j in range(weight[0], bag + 1):
    dp[0][j] = value[0]

for i in range(1, n):
    for j in range(bag + 1):
        if j < weight[i]:
            dp[i][j] = dp[i - 1][j]
        else:
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

print(dp[n - 1][bag])

0-1背包问题,一维

思路

  1. 定义:dp[j] 表示当前考虑的物品范围内,背包容量为 j 时能获得的最大价值。
  2. 状态转移方程:dp[j] = max(dp[j], dp[j - w] + v) (j >= w)。
  3. 初始化:dp = [0] * (bag + 1)。

解答

python 复制代码
first_line = input().split()
n = int(first_line[0])
bag = int(first_line[1])

second_line = input().split()
third_line = input().split()
weight = [int(x) for x in second_line]
value = [int(x) for x in third_line]

dp = [0] * (bag + 1) # dp[j] 表示容量 j 能获得的最大价值

for i in range(n):
    w = weight[i]
    v = value[i]
    # 逆序遍历,保证每种物品只选一次
    for j in range(bag, w - 1, -1):
        dp[j] = max(dp[j], dp[j - w] + v)

print(dp[bag])

LeetCode:416. 分割等和子集

https://leetcode.cn/problems/partition-equal-subset-sum/description/
添加链接描述

思路

转化为01-背包问题:每个元素只能选或不选,背包容量为 target,求是否能恰好装满。

解答

python 复制代码
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        total = sum(nums)
        # 总和为奇数则无法平分
        if total % 2 != 0:
            return False
        
        target = total // 2
        n = len(nums)
        
        # dp[j] 表示当前已考虑的元素能否凑出和为 j
        dp = [False] * (target + 1)
        dp[0] = True
        
        for num in nums:
            # 从后往前更新,避免重复使用当前元素
            for j in range(target, num - 1, -1):
                dp[j] = dp[j] or dp[j - num]
        
        return dp[target]
相关推荐
万化冥合27 分钟前
怎么批量把 Word 转 PDF?
python·pdf·c#·word
Rain的Java大神之路28 分钟前
面了 50 个候选人,90% 都挂在 LeetCode 3 无重复字符的最长子串:滑动窗口的 5 个致命坑
java·后端·leetcode
~城南花已开~32 分钟前
Redfish 事件接收服务搭建指南(Ubuntu Server 实测)
linux·服务器·python·ubuntu
fengyangaiGEO33 分钟前
如何通过GEO优化实现外贸B2B询盘增长?
人工智能·python
jianxuan44 分钟前
Spring Boot + Maven 接入 Allatori:从普通打包到可选混淆发布
spring boot·python·maven
不一样的故事1261 小时前
Prompt 工程(Prompt Engineering)
前端·人工智能·python
我命由我123451 小时前
6-2.Python 异常处理 - 异常捕获(捕获指定异常、常见异常类型、异常信息)
java·运维·开发语言·python·http·https·java-ee
zh路西法1 小时前
【模型式强化学习】(三):MBPO——短轨迹生成与模型数据驱动的策略优化
python·强化学习·pe·sac·pets·mbpo·mbrl
Angeldream1231 小时前
第 9 章 医学影像项目实战
大数据·图像处理·人工智能·python·医学影像处理
ZhengEnCi1 小时前
一亿条数据取前100条完全指南:从全量排序到分块流式最小堆的4种解法实测
python·算法·排序算法