首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【算法】动态规划专题⑥ —— 完全背包问题 python

  • 25-02-16 16:40
  • 4566
  • 13732
blog.csdn.net

目录

  • 前置知识
  • 进入正题
  • 模板


前置知识


【算法】动态规划专题⑤ —— 0-1背包问题 + 滚动数组优化


完全背包问题是动态规划中的一种经典问题,它与0-1背包问题相似,但有一个关键的区别:在完全背包问题中,每种物品都有无限的数量可用。也就是说,你可以选择同一种物品多次放入背包,以使背包中的总价值最大。

示例分析
假设物品重量为 (w = [2, 3]),价值为 (v = [3, 4]),容量 (C = 5):

容量 (j)012345
初始化000000
物品1(w=2)003366
物品2(w=3)003467

最优解:选取 1 个物品1(重量2,价值3)和 1 个物品2(重量3,价值4),总价值为7。



进入正题


状态定义

设 dp[i][j] 表示前 (i) 种物品,背包容量为 j 时的最大总价值。

状态转移方程的推导

核心思想:

对第 (i) 种物品,可以选择 0 次或多次,因此需要枚举所有可能的选取次数。

暴力枚举

对每种物品 (i) 和容量 (j),假设选取 (k) 次物品 (i),则转移方程为:

缺点:时间复杂度为 (O(n * C * kmax),其中 kmax= C/ w i w_i wi​ ,效率极低。


优化推导(消除对 k 的显式枚举)

观察到以下递推关系:

在这里插入图片描述

数学证明:

假设在容量 (j) 时,最优解中包含 (m \geq 1) 个物品 (i),则总价值为:
dp[i][j] = dp[ i i i][ j j j - w i w_i wi​] + v i v_i vi​
这是因为在 ( j j j - w i w_i wi​) 容量时,已经考虑了选取 (m-1) 个物品 (i) 的最优解。

因此,状态转移方程简化为:
dp[i][j] = max ( dp[i-1][j], dp[ i i i][ j j j - w i w_i wi​] + v i v_i vi​ )



模板


完全背包问题 https://www.acwing.com/problem/content/3/

有 N N N 种物品和一个容量是 V V V 的背包,每种物品都有无限件可用。
第 i i i 种物品的体积是 v i v_i vi​,价值是 w i w_i wi​。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
​
输入格式
​
第一行两个整数, N , V N,V N,V,用空格隔开,分别表示物品种数和背包容积。
接下来 N N N 行,每行两个整数 v i , w i v_i, w_i vi​,wi​,用空格隔开,分别表示第 i i i 种物品的体积和价值。
​
输出格式
​
输出一个整数,表示最大价值。
​
数据范围
​

0 < N , V ≤ 1000 0 \lt N, V \le 1000 0<N,V≤1000
0 < v i , w i ≤ 1000 0 \lt v_i, w_i \le 1000 0<vi​,wi​≤1000
​
输入样例

4 5
1 2
2 4
3 4
4 5
  • 1
  • 2
  • 3
  • 4
  • 5

输出样例:

10
  • 1

code:

n, v = map(int, input().split())
dp = [[0] * (v + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
    wi, vi = map(int, input().split())
    for j in range(1, v + 1):
        if j - wi >= 0:
            dp[i][j] = max(dp[i - 1][j], dp[i][j - wi] + vi)
        else:
            dp[i][j] = dp[i - 1][j]
print(dp[n][v])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

滚动数组优化:

n, v = map(int, input().split())
dp = [0] * (v + 1)
for i in range(1, n + 1):
    wi, vi = map(int, input().split())
    for j in range(wi, v + 1):
        dp[j] = max(dp[j], dp[j - wi] + vi)
print(dp[v])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

不了解 滚动数组优化 的可点此进入


END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢


注:本文转载自blog.csdn.net的查理零世的文章"https://blog.csdn.net/2401_87245677/article/details/145484218"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top