蓝桥杯(5):python动态规划DF[2:背包问题]

1 0-1背包介绍【每件物品只能拿1件或者不拿】

1.1 简介

贪心是不可以的!!!

1.2 状态 及状态转移

转移解释:要么不选 则上一个直接转移过来【dp[i-1][j]】,要么是选这个之后体积为j 则上一个对应的就是【dp[i-1][j-wi] + v[i]】 选上这个之后价值叫上哦!!1

1.3 代码

n,v= list(map(int,input().split()))
w = [0]
value = [0]
for i in range(n):
    w_v = list(map(int,input().split()))
    w.append(w_v[0])
    value.append((w_v[1]))
# print(w)
# print(value)
'''容量总共为V
不超过v的时候价值最大
求最大价值--是矩阵中的值,那么还有两个指标分别是 物品数和容量
dp[i][j]表示前i个物品当体积为j时对应的价值'''

'''找到状态之后 想状态转移方程:
如果第i个物品不拿 dp[i][j] = dp[i-1][j]
如果第i个物品拿 dp[i][j] = dp[i-1][j-w[i]]+value[i]
要最大的价值 则选最大的 决定拿还是不拿'''
dp = [[0]*(v+1) for i in range(n+1)]
for i in range(1,n+1):
    for j in range(1,v+1):
        if j>=w[i]: # 说明存在第i个拿出来这种情况
            dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+value[i])
        else:
            dp[i][j] = dp[i-1][j]

print(dp[n][v])

2 滚动数组优化

发现在上方的代码中 更新第i行只用到了i-1行的数据,所有可以把空间压缩为2

然后对代码做以下改变即可

3 完全背包【每件物品可以拿0件1件2件一直到无数件】

3.1 定义

每个物品可以不拿或者拿一件 两件。。。这样

有三个参数了现在,依次枚举i,j,k 三重循环时间代价太大了

怎么优化时间呢?

3.2 代码实现

n,v= list(map(int,input().split()))
w = [0]
value = [0]
for i in range(n):
    w_v = list(map(int,input().split()))
    w.append(w_v[0])
    value.append((w_v[1]))
# print(w)
# print(value)

dp = [[0]*(v+1) for i in range(n+1)]
for i in range(1,n+1):
    for j in range(1,v+1):
        if j>=w[i]: # 说明存在第i个拿出来这种情况
            dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]]+value[i])
        else:
            dp[i][j] = dp[i-1][j]

print(dp[n][v])

4 多重背包【0-1背包和完全背包的结合体】

4.1 定义

每种物品可是可以多拿但是有一个上限!!

不拿的情况也包含在上面的那个式子里了,所以更新值只需要 和自己比 留下最大的即可!!!

完全背包没有办法控制上限,所以我们只能老老实实的三重循环。。。

4.2 三重循环代码

n,v= list(map(int,input().split()))
w = [0]
value = [0]
s = [0]
for i in range(n):
    w_v_s = list(map(int,input().split()))
    w.append(w_v_s[0])
    value.append(w_v_s[1])
    s.append(w_v_s[2])
# print(w)
# print(value)
'''容量总共为V
不超过v的时候价值最大
求最大价值--是矩阵中的值,那么还有两个指标分别是 物品数和容量
dp[i][j]表示前i个物品当体积为j时对应的价值'''

'''找到状态之后 想状态转移方程:
如果第i个物品不拿 dp[i][j] = dp[i-1][j]
如果第i个物品拿 dp[i][j] = dp[i-1][j-w[i]]+value[i]
要最大的价值 则选最大的 决定拿还是不拿'''
dp = [[0]*(v+1) for i in range(n+1)]
for i in range(1,n+1):
    for j in range(1,v+1):
        for m in range(0, min(s[i],j//w[i])+1):
            # if j >= m*w[i]: # 说明存在第i个拿出来这种情况
            dp[i][j] = max(dp[i][j], dp[i-1][j-m*w[i]]+m*value[i])
            # 和0-1背包的区别就是dp[i-1][j-w[i]]变成了dp[i][j-w[i]]
            # else:
            #     dp[i][j] = dp[i][j]

print(dp[n][v])

4.3 二进制优化后代码

新策略:二进制的拆si  !!!!!!!!!!!!!

普通拆发:

二进制的拆法:

##二进制优化
import sys


def put(_w, _v):
    for j in range(v, _w - 1, -1):
        dp[j] = max(dp[j], dp[j-_w] + _v)


n, v = map(int, sys.stdin.readline().split())
dp = [0]*(v + 1)
for _ in range(n):
    weight, value, i = map(int, sys.stdin.readline().split())
    tmp = 1
    while i >= tmp:
        put(weight * tmp, value * tmp)
        i -= tmp
        tmp <<= 1
    if i > 0:
        put(weight * i, value * i)
print(dp[v])

5 二维费用背包

5.1 定义

状态转移方程:

空间上受不了,用滚动数组

可以把i删掉

5.2 代码

N,V,M=map(int, input().split())
dp = [[0]*(M+1) for i in range(V+1)]

for i in range(1,N+1):
    vi,mi,wi = map(int, input().split())
    for j in range(V,vi-1,-1):
        for k in range(M,mi-1,-1):
            #dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-vi][k-mi]+wi)
            dp[j][k] = max(dp[j][k], dp[j-vi][k-mi]+wi)
print(dp[V][M])

6 分组背包

很像01背包

'''
分组背包:
每组中只能选择一个物品
状态转移方程与0-1背包一样,唯一的区别是:在更新状态时要多与自己比较一次
不用一维滚动数组优化时,遍历顺序是每组,组中每个元素,背包容量
使用一维滚动数组优化时,遍历顺序是每组,背包容量,组中每个元素(可防止组中元素被选择多次)
'''

##1、没有优化空间
N,V = map(int,input().split())
dp = [[0]*(V+1) for i in range(N+1)]
# dp[i][j]表示前i组物品体积不超过j的最大价值
#最终的答案dp[N][V]

for i in range(1,N+1): # 对于每个组
  s = int(input())
  for q in range(s): # 对于每个组中的每个物品
    w,v = map(int,input().split())   #获取每个物品的质量与价值
    for j in range(0,V+1):   #对于当前背包容量
      if j< w:   #分组背包更新状态时,要比其他背包多一次比较,即要与本身做一次比较
        dp[i][j] = max(dp[i][j], dp[i-1][j])
      else:
        dp[i][j] = max(dp[i][j],dp[i-1][j],dp[i-1][j-w] + v)

print(dp[N][V])


#2.两行滚动数组优化

N,V = map(int,input().split())
dp = [[0]*(V+1)for i in range(2)]

for i in range(1,N+1):#对于每个组
  s = int(input())
  for _ in range(s): #对于每个组中的每个物品
    w,v = map(int,input().split())   #获取每个物品的质量与价值
    for j in range(1,V+1):   #对于当前背包容量
      if j< w:   #分组背包更新状态时,要比其他背包多一次比较,即要与本身做一次比较
        dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][j])
      else:
        dp[i%2][j] = max(dp[i%2][j],dp[(i-1)%2][j],dp[(i-1)%2][j-w] + v)

print(dp[N%2][V])


#3 一维滚动数组优化 YYDS
N,V = map(int,input().split())
dp = [0]*(V+1)
for i in range(1,N+1):#对于每个组
  s = int(input())
  group =  []
  for _ in range(s): #对于每个组中的每个物品
    group.append([*map(int,input().split())])
  #分组包采用一维滚动数组时,需先遍历背包容量,再遍历每组每个物品的质量与价值,否则会出现一组中的物品被选择多次的情况
  for j in range(V,-1,-1):   #对于当前背包容量
    for w,v in group:   #获取每个物品的质量与价值
      if j>=w:  #背包容量不能小于物品质量,不然装不了
        #分组背包更新状态时,要比其他背包多一次比较,即要与本身做一次比较
        dp[j] = max(dp[j],dp[j-w] + v)
print(dp[V])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/518664.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue 样式技巧总结与整理[中级局]

SFC&#xff08;单文件组件&#xff09;由 3 个不同的实体组成&#xff1a;模板、脚本和样式。三者都很重要&#xff0c;但后者往往被忽视&#xff0c;即使它可能变得复杂&#xff0c;且经常导致挫折和 bug。 更好的理解可以改善代码审查并减少调试时间。 这里有 7 个奇技淫巧…

CSS设置网页颜色

目录 前言&#xff1a; 1.颜色名字&#xff1a; 2.十六进制码&#xff1a; 3.RGB&#xff1a; 4.RGBA&#xff1a; 5.HSL&#xff1a; 1.hue&#xff1a; 2.saturation&#xff1a; 3.lightness&#xff1a; 6.HSLA&#xff1a; 前言&#xff1a; 我们在电脑显示器&…

高血压的常见症状,你是否了解并警惕?

高血压是一种慢性心血管疾病&#xff0c;它的形成和发展与很多种因素密切相关。导致高血压的重要因素之一就是不良的生活饮食习惯。 高血压严重危害着人的心脏、肾脏、大脑等这些人体重要的器官&#xff0c;会容易带来心脏病、肾功能衰竭等一系列疾病。今天我在来为大家讲解一…

CorelDRAW2024序列号破解版下载以及CorelDRAW新功能介绍

CorelDRAW Graphics Suite 2024破解版介绍 CorelDRAW Graphics Suite 2024 破解版是领先的专业图形设计软件套件&#xff0c;旨在提供多个精心设计的工具和丰富的功能&#xff0c;轻松提高您的技能睡哦平&#xff0c;您可以更好的完成矢量插图、完美的布局、高级的照片编辑和高…

Jeecg commonController 任意文件上传漏洞复现

0x01 产品简介 Jeecg(J2EE Code Generation)是一款基于代码生成器的低代码开发平台,使用JEECG可以简单快速地开发出企业级的Web应用系统。 0x02 漏洞概述 JEECG(J2EE Code Generation) 是开源的代码生成平台,目前官方已停止维护。由于 /api 接口鉴权时未过滤路径遍历,攻…

中高级前端? 这些一元运算符,你真的搞清楚了吗

前言 一元运算符&#xff0c;不太起眼&#xff0c;作用很大&#xff0c;请别忽视她&#xff01; 走近她&#xff0c;爱上她&#xff01; 定义 只需要一个操作数的运算符称为一元运算符。 还是代码容易懂&#xff1a; 1 // 一个操作数1 2 // 两个操作数一元运算符清单 运…

基于Springboot的学校防疫物资管理平台(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的学校防疫物资管理平台&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

安装typora 免费版(beta版)

前言 typora 2021年11 月 23日后&#xff0c;推出付费的正式版本。不想花钱购买&#xff0c;除了破解脚本&#xff0c;还有其他的办法吗&#xff1f; 程序下载 答案是有的。可以安装免费的Typora Beta 版本&#xff0c;该旧版本基本的功能一应俱全&#xff0c;应付轻度的mar…

若依自带vue-cropper上传图片(可旋转、缩放)

2024.4.4今天我学习了如何使用若依的vue-cropper上传图片组件&#xff0c;在工作中遇到一个需求&#xff0c;需要对上传的图片进行旋转的操作&#xff0c;然后我先找到el-upload组件&#xff0c;使用之后发现它有一个自动上传和非自动上传的功能&#xff0c;是不是就可以通过非…

【React】useState为何返回数组而非对象

useState的正确语法如下 const [count, setCount] useState(0)通过打印可以看到useState返回一个数组&#xff0c;那么为何不返回对象呢 涉及到数组与对象间解构方式的差异 数组的解构&#xff1a;根据索引 const [a,,b] [1,2,3] console.log(a) // 1 console.log(b) // 3…

CentOS7安装MySQL8.0.28(持续)

第一步 &#xff1a;下载mysql MySQL https://www.mysql.com/

【java探索之旅】逻辑控制掌握 顺序结构 分支语句

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、逻辑控制的概念二、顺序结构三、分支结构3.1 if语句3.2 if习题巩固3.3 细节注意项…

阿里云服务器地域哪个便宜?哪个地域优惠?

目前2024年阿里云服务器地域对比哪个价格更优惠&#xff1f;华北6&#xff08;乌兰察布&#xff09;、华北3&#xff08;张家口&#xff09;、华北1&#xff08;青岛&#xff09;和华南2&#xff08;河源&#xff09;地域更便宜&#xff0c;云服务器吧yunfuwuqiba.com整理阿里云…

快排序解读

排序算法是计算机科学中不可或缺的一部分&#xff0c;它们在各种数据处理场景中发挥着关键作用。在众多排序算法中&#xff0c;快速排序以其高效的性能和简洁的实现成为了许多程序员的首选。今天&#xff0c;我们就来深入剖析快速排序算法&#xff0c;了解其原理、实现方式以及…

ES学习日记(五)-------插件head安装

接上回,必要的git和node已经装完了,现在开始装head 回到es集群项目里找到plugins(插件文件夹下), 存在安装在plugins启动es报错的情况,报错信息如图一,解决方案就是换个目录,不要放在plugin目录下 git clone https://github.com/mobz/elasticsearch-head.git 打开远程登陆,默…

浅谈偏向锁、轻量级锁、重量级锁

为了换取性能&#xff0c;JVM在内置锁上做了非常多的优化&#xff0c;膨胀式的锁分配策略就是其一。理解偏向锁、轻量级锁、重量级锁的要解决的基本问题&#xff0c;几种锁的分配和膨胀过程&#xff0c;有助于编写并优化基于锁的并发程序。 内置锁的分配和膨胀过程较为复杂&…

Python学习: 错误和异常

Python 语法错误 解析错误(Parsing Error)通常指的是程序无法正确地解析(识别、分析)所给定的代码,通常是由于代码中存在语法错误或者其他无法理解的结构导致的。这可能是由于缺少括号、缩进错误、未关闭的引号或其他括号等问题造成的。 语法错误(Syntax Error)是指程序…

创新性的智慧公厕技术研发与应用

智慧公厕&#xff0c;作为城市基础设施的重要组成部分&#xff0c;扮演着提供舒适便捷卫生服务的角色。智慧公厕源头实力厂家广州中期科技有限公司&#xff0c;通过技术创新与应用升级&#xff0c;打造标杆性的智慧公厕整体解决方案。通过创新性的技术应用&#xff0c;智慧公厕…

Redis入门--头歌实验Redis事务与流水线

任务描述 本关任务&#xff1a;编写一个商品交易平台的后端处理逻辑。 相关知识 手机、互联网普遍的当下&#xff0c;系统会同时处理多客户端的请求&#xff0c;而在多客户端同时处理相同的数据时&#xff0c;数据一致性就变得十分重要&#xff0c;稍不谨慎的操作就会导致数据出…

Linux操作系统逻辑、线性、物理地址,带你轻松理解Linux运维-Hook机制

虚拟内存&#xff08;Virtual Memory&#xff09;是指计算机呈现出要比实际拥有的内存大得多的内存量。因此他允许程式员编制并运行比实际系统拥有的内存大得多的程式。这使得许多大型项目也能够在具有有限内存资源的系统上实现。一个非常恰当的比喻是&#xff1a;你不必非常长…
最新文章