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

news2025/2/24 7:53:39

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.coloradmin.cn/o/1586013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4.Hexo 页面属性和模板设置

Frontmatter frontmatter基本上是可以定义的有关不同文件的信息&#xff0c;本质上是元数据 frontmatter是我们可以分配给每个内容页面的信息 在Hexo中创建文件时&#xff0c;Hexo主题可以使用该信息以不同的方式显示该内容 当在Hexo创建了一个文件&#xff0c;在source文件夹…

【MATLAB源码-第12期】基于matlab的4FSK(4CPFSK)的误码率BER理论值与实际值仿真。

1、算法描述 4FSK在频移键控&#xff08;FSK&#xff09;编码的基础上有所扩展。FSK是一种调制技术&#xff0c;它通过在不同频率上切换来表示不同的数字或符号。而4FSK则是FSK的一种变种&#xff0c;表示使用了4个不同的频率来传输信息。 在4FSK中&#xff0c;每个数字或符号…

信号继电器DX-31B 额定值1A 柜内安装,板前接线 约瑟JOSEF

系列型号 DX-31B信号继电器DX-31BJ信号继电器 DX-32A信号继电器DX-32AJ信号继电器 DX-32B信号继电器DX-32BJ信号继电器 DX-31A信号继电器DX-33/1信号继电器 DX-33/2信号继电器DX-33/3信号继电器 DX-33/4信号继电器DX-33/5信号继电器 ​用途 DX信号继电器用于电力系统继…

本地自动备份的设置方法,终于不担心数据丢失了

前言 这几天陆续有小伙伴在公众号后台发送【同步】&#xff0c;想要找找看有没有适合本地的同步/备份软件。今天小白终于有时间给小伙伴们更新这类型的教程了。 本地自动备份的软件肯定是有的&#xff0c;只是好像使用的人比较少&#xff0c;所以就没有太多教程。 虽然说可以…

Excel 防止数字变为E+的技巧

方式一&#xff1a;开始选项卡 ⇒ 分数 方式二&#xff1a;设置单元格格式 ⇒ 自定义 ⇒ 0 方式三 设置单元格格式为纯文本后&#xff0c;在粘贴数据当数字过长的时候(例如身份证号)&#xff0c;超过15位之后的数字都会变成0。 此时可以在数字前添加一个符号&#xff0c;例如 …

2024-4-11-arm作业

汇编实现三个灯的闪烁 源代码&#xff1a; .text .global _start _start: 时钟使能LDR r0,0x50000A28ldr r1,[r0]orr r1,r1,#(0x1<<4)str r1,[r0]设置PE10输出LDR r0,0x50006000ldr r1,[r0]bic r1,r1,#(0x3<<20)orr r1,r1,#(0x1<<20)str r1,[r0]设置PE1…

Green Hills 自带的MULTI调试器查看R7芯片寄存器

Green Hills在查看芯片寄存器时需要导入 .grd文件。下面以R7为例&#xff0c;演示一下过程。 首先打开MULTI调试器&#xff0c;如下所示View->Registers&#xff1a; 进入如下界面&#xff0c;选择导入寄存器定义文件.grd&#xff1a; 以当前R7芯片举例&#xff08;dr7f7013…

天诚智慧校园管理系统,变革高校物联网锁数智化通行新模式

三月草长莺飞&#xff0c;四月柳绿莺啼&#xff0c;在万物复苏的美好时节&#xff0c;历经半年的精心酝酿与匠心打磨&#xff0c;全场景AIoT解决方案服务商——江苏新巢天诚智能技术有限公司&#xff08;以下简称“天诚”&#xff09;正式推出新一代高校数智化通行管理平台——…

如何将CSDN的文章以PDF文件形式保存到本地

1.F12 打开开发者工具窗口 2.console下输入命令 (function(){$("#side").remove();$("#comment_title, #comment_list, #comment_bar, #comment_form, .announce, #ad_cen, #ad_bot").remove();$(".nav_top_2011, #header, #navigator").remove…

syncfusion-diagram:demo1如何实现

xmlns:syncfusion"http://schemas.syncfusion.com/wpf" xmlns:stencil"clr-namespace:Syncfusion.UI.Xaml.Diagram.Stencil;assemblySyncfusion.SfDiagram.WPF"当我们进入syncfusion的diagram中&#xff0c;可以看到&#xff0c;一个非常炫酷的例子 不仅实…

【2024.4.11练习】国际象棋

题目描述 题目思路 棋盘类问题是一类典型的状态压缩dp问题&#xff0c;将0设为不摆放象棋&#xff0c;1设为摆放象棋。这样棋盘的每一列都可以变成01的序列。每一列有8个格子&#xff0c;所以每列总共有种摆放情况。为了完成递推&#xff0c;需要写出以下功能的预处理函数 ini…

无缝集成:使用Spring Boot和Vue实现头像上传与回显功能

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

STC89C52学习笔记(五)

STC89C52学习笔记&#xff08;五&#xff09; 综述&#xff1a;文本讲述了代码中速写模板的创建、如何将矩阵键盘的按键与数字一一对应以及如何创建一个矩阵键盘密码锁。 一、速写模板 点击“templates”&#xff0c;再鼠标右键选择配置&#xff0c;按照以下方式即可修改一些…

正压自动放水器

劣质产品或许能骗一个人 却骗不了一群人 更骗不了五湖四海的人 因为品质&#xff0c;所以传播因为认同&#xff0c;所以分享 一、正压放水器概述&#xff1a; 正压自动放水器的型号为CWG-ZY&#xff0c;C指瓦斯抽放&#xff08;采&#xff09;中抽放&#xff08;采&#xff…

Linux系统概述与安装

Linux的介绍 Linux内核 Linux内核是 Linux 操作系统主要组件&#xff0c;也是计算机硬件与其软件之间的交互入口。它负责两者之间的通信&#xff0c;还要尽可能高效地管理资源 Linux Shell shell是系统的用户界面&#xff0c;提供了用户与内核进行交互操作的一种接口 Linux文…

Vmware虚拟机Centos7固定IP地址

1、点击编辑-虚拟网络编辑器 2、点击更改设置、修改虚拟网络配置器并确认保存&#xff08;见图&#xff09; 这个子网IP和子网掩码的前三位需要一样网关的前三位需要和子网ip一致。 3、打开设置“网络和Internet”&#xff0c;点击“更改适配器选项”&#xff0c;点击适配器VM…

Github第一Star数的国产免费开源防火墙--雷池社区版初步体验

前言 近期准备搭建一个博客网站&#xff0c;用来存储工作室同学们的学习笔记。服务器准备直接放在公网上&#xff0c;方便大家随时随地的上传和浏览&#xff0c;为了防止网站被人日穿成为肉鸡&#xff0c;一些防御措施还是要部署的。 首先明确自己的需求&#xff1a; 零成本…

【数据结构】双向链表 C++

一、什么是双向链表 1、定义 双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c;从双向链表中的任意一个结点开始&#xff0c;都可以很方便地访问它的前驱结点和后继结点。 双…

企业工商信息查询API接口有哪些

当今社会我们几乎每天都在和一些企业打交道&#xff0c;有时候需要确认下这家企业经营范围&#xff0c;注册地址等信息&#xff0c;那怎么办呢&#xff0c;这个时候就需要一些企业工商信息查询的API接口了。 有的时候你可以只知道这家公司的大概企业名称&#xff0c;比如数脉&…

Python中sort()函数、sorted()函数的用法深入讲解(具体实例:蓝桥杯数位排序)

前置知识&#xff1a; 可迭代对象的定义&#xff1a;可迭代对象是指可以被迭代或遍历的对象&#xff0c;即可以使用循环结构对其进行逐个访问的对象。 在Python中常见的可迭代对象有&#xff1a;列表(list)、元组&#xff08;tuple&#xff09;、字符串&#xff08;sting&…