【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]
相关推荐
“AI国潮设计-小江”1 小时前
《Python+SDXL实战:用ControlNet精准控制“英歌舞翻糖吐司”构图,附批量生成脚本》
开发语言·人工智能·python·prompt·aigc
wenwen_chao2 小时前
Python学习与开发资源合集:实用技巧与工具推荐
python
奋发向前wcx2 小时前
CSP-J复赛模拟赛4 王晨旭补题 2026.10.5
算法
for_ever_love__3 小时前
函数——参数、lambda、*args与作用域
python·函数·大模型开发·编程基础
东莞市云毅网络有限公司3 小时前
企业资料时效性判定:Last-Modified、正文日期与版本字段三路交叉
python·sqlite·自动化运维·geo·数据监测
Query*3 小时前
深入浅出LangGraph【一】_基础篇
python·ai·langchain
XiaoMaqqqq3 小时前
市面上正规的IP驱动产业新场景新工具哪家强
运维·python·网络协议·tcp/ip
ShyanZh4 小时前
【Python3基础】19-Socket 与 TCP、UDP 编程
python·网络协议·tcp/ip·udp
念何架构之路4 小时前
zap采样器与性能优化内幕
算法·性能优化·哈希算法
惊讶的猫4 小时前
工具选对之后还不够:商城 Agent 的参数与权限治理
开发语言·python