当前位置: 首页 > news >正文

动态规划之0-1背包问题

动态规划之0-1背包问题

文章目录

    • 动态规划之0-1背包问题
      • 一、先给出代码
      • 二、讲解
        • 第一步:初始化
        • 第二步:动态规划,填表
        • 第三步:回溯,找到选择方案
        • 总结
      • 三、进阶(用一维数组解决问题)


一、先给出代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Bp(vector<int >&weights, vector<int> &values, vector<vector<int>>& dp,int bag_weight,vector<int>&result)
{//初始化for (int j = weights[0]; j <= bag_weight; j++) {dp[0][j] = values[0];}//动态规划,填表//因为第一行是要单独初始化的,后面还要建立在第一行的基础上,所以i初始值为1for (int i = 1; i < weights.size(); i++) {for (int j = 0; j <= bag_weight; j++) {//第一种情况,第i个物品就算单独放也不行;第二种情况,拿上一个没i的结果和有i的比较if (j < weights[i]) {dp[i][j] = dp[i - 1][j];}else {dp[i][j] = max(dp[i - 1][j], dp[i-1][j-weights[i]] + values[i]);}}}//统计拿走的东西种类for (int i = weights.size() - 1, j = bag_weight; i > 0; i--) {if (dp[i][j] > dp[i - 1][j]) {result.push_back(i);j -= weights[i];}if (i == 1 && dp[i][j] !=values[i]) {//如果dp[1][j]的不等于values[1]result.push_back(0);}}
}int main()
{int num,weight, value,bag_weight;vector <int> weights ;vector<int> values ;vector<int>result;cout << "Please enter the number of weights and values!" << endl;//输入东西种类数量cin >> num;//分别输入重量和价值cout << "Please enter the  weights! " << endl;for (int i = 0; i < num;i++) {cin >> weight;weights.push_back(weight);}cout << "Please enter the values!" << endl;for (int i = 0; i < num; i++) {cin >> value;values.push_back(value);}cout << "Please enter the weight of bag!" << endl;cin>> bag_weight ;vector<vector<int>> dp(weights.size() + 1, vector<int>(bag_weight + 1, 0));Bp(weights,values,dp,bag_weight,result);//输出总额和拿走的东西种类cout <<"The total prize is :" << dp[weights.size() - 1][bag_weight] << endl;cout << "The way of result is :" << endl;for (auto it = result.rbegin(); it != result.rend();it++) {cout << *it << " ";}return 0;
}

二、讲解

关于dp数组:

**dp[i][j]表示在考虑前i个物品,并且背包容量为j的情况下,能够获得的最大价值。**这样的一个二维数组可以用来记录不同状态下的最优解,其中i表示物品的编号(从0开始),j表示背包的容量。根据题目的要求,我们希望找到dp[weights.size() - 1][bag_weight],即在考虑所有物品,且背包容量为bag_weight的情况下,能够获得的最大价值。

第一步:初始化

for (int j = weights[0]; j <= bag_weight; j++) {dp[0][j] = values[0];
}

在动态规划中,我们通常需要构建一个状态转移表格(dp数组)来记录状态的变化,在01背包问题中,我们有两个状态:背包容量和物品编号。这里的代码初始化了第一行,表示只有第一个物品时,对于不同背包容量的情况下,能够获得的最大价值。这是一个边界条件,因为只有一个物品,所以它要么放入背包,要么不放入,所以只有当背包容量大于等于第一个物品的重量时,才能将其放入背包,获得对应的价值

第二步:动态规划,填表

for (int i = 1; i < weights.size(); i++) {for (int j = 0; j <= bag_weight; j++) {if (j < weights[i]) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);}}
}

这部分代码构建了整个dp数组。在这里,我们逐步考虑每个物品,以及在不同背包容量下获得的最大价值。对于每个物品,我们有两个选择:放入背包或者不放入背包。每个单元格dp[i][j]的值是根据以下两种情况来确定的:

  1. 如果第i个物品的重量weights[i]大于当前背包容量j,那么不能将第i个物品放入背包,所以最大价值与上一个状态dp[i-1][j]相同。
  2. 如果第i个物品的重量weights[i]小于等于当前背包容量j,那么我们有两种选择:放入第i个物品或者不放入。我们需要比较这两种选择对应的最大价值,选择其中较大的值作为dp[i][j]的值。

第三步:回溯,找到选择方案

for (int i = weights.size() - 1, j = bag_weight; i > 0; i--) {if (dp[i][j] > dp[i - 1][j]) {result.push_back(i);j -= weights[i];}if (i == 1 && dp[i][j] != values[i]) {result.push_back(0);}
}

这部分代码用于回溯,找出实际选择了哪些物品放入背包,从而达到最大价值。从dp数组的右下角(即dp[weights.size() - 1][bag_weight])开始,我们倒退遍历dp数组。如果发现当前位置的最大价值与上一行相同,说明当前物品没有放入背包,我们直接跳到上一行;如果不同,说明当前物品放入了背包,我们将其记录在result中,并将背包容量减去该物品的重量,然后继续向上遍历。还有一种额外情况,就是如果在遍历到第一个物品时,背包容量还有剩余,且最终的最大价值不等于第一个物品的价值,说明第一个物品也被放入了背包。

总结

这个算法的思路是通过动态规划解决01背包问题。它从初始状态出发,通过填充dp数组来逐步构建出最优解。然后通过回溯,找出实际的选择方案。在动态规划的过程中,关键在于将问题分解为子问题,通过比较不同选择来得出最优解,最终获得整体的最优解。

三、进阶(用一维数组解决问题)

我们创建了一个一维向量 dp,其中 dp[i] 表示在背包容量为 i 时可以达到的最大总价值。这个向量的长度是 bag_Weight + 1,因为背包的容量从0到bag_Weight

现在让我们来思考动态规划的递推过程。我们要从第一个物品开始,逐步考虑加入更多的物品,直到考虑完所有物品。为了实现这个过程,我们使用了两个嵌套的循环。外层循环遍历所有的物品,内层循环遍历从背包的最大承重开始,逐步减少背包的容量。

在内层循环中,我们要考虑两种情况:放入当前物品和不放入当前物品。我们通过比较这两种情况来决定背包在当前容量下的最优解。具体来说,如果当前物品的重量不超过背包的当前容量(即 j >= weight[i]),我们就可以尝试放入这个物品,然后在背包剩余容量为 j - weight[i] 时找到前一个状态的最优解,加上当前物品的价值。这个过程保证了在考虑前 i 个物品的情况下,背包容量为 j 的最优解。

在比较放入和不放入当前物品的情况后,我们将较大的值赋给 dp[j],表示背包容量为 j 时的最大总价值。这个过程通过逐渐增加物品数量和背包容量,使得我们可以在最终考虑完所有物品时,得到背包的最优解。

最终,当我们完成外层和内层循环后,dp[bag_Weight] 就存储了问题的最终解,即背包的最大总价值。我们输出这个值,就完成了整个过程。

为什么for循环外层遍历物品,而内层遍历重量?

  1. 外层循环遍历物品(i 的变化): 当我们考虑第 i 个物品时,我们已经考虑了前 i-1 个物品的情况,假设这些子问题的解已经计算出来并存储在 dp 数组中。外层循环在不同的 i 值下,使得我们能够逐个考虑每个物品,并在 dp 数组中记录之前子问题的解。
  2. 内层循环遍历背包容量(j 的变化): 对于每个物品 i,我们需要考虑在背包容量从 bagWeight 逐渐减少到 0 的过程中,如何得到最大总价值。这是因为我们希望逐步填充 dp 数组中更大的背包容量,依赖于之前较小容量下的最优解。通过从 bagWeight 减少到 0 的循环顺序,我们可以确保在计算当前背包容量 j 下的最优解时,之前的更小容量下的解已经计算出来。
#include<iostream>
using namespace std;
#include <vector>
void Bp() {vector<int> weight = { 1, 3, 4 };vector<int> value = { 15, 20, 30 };int bag_Weight = 4;vector<int> dp(bag_Weight + 1, 0);for (int i = 0; i < value.size(); i++) {for (int j = bag_Weight; j >= weight[i]; j--) {dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);}}cout << dp[bag_Weight] << endl;
}int main() {Bp();
}

相关文章:

动态规划之0-1背包问题

动态规划之0-1背包问题 文章目录 动态规划之0-1背包问题一、先给出代码二、讲解第一步&#xff1a;初始化第二步&#xff1a;动态规划&#xff0c;填表第三步&#xff1a;回溯&#xff0c;找到选择方案总结 三、进阶&#xff08;用一维数组解决问题&#xff09; 一、先给出代码…...

为什么需要单元测试?

为什么需要单元测试&#xff1f; 从产品角度而言&#xff0c;常规的功能测试、系统测试都是站在产品局部或全局功能进行测试&#xff0c;能够很好地与用户的需要相结合&#xff0c;但是缺乏了对产品研发细节&#xff08;特别是代码细节的理解&#xff09;。 从测试人员角度而言…...

《合成孔径雷达成像算法与实现》Figure3.13——匹配滤波器的三种实现方式

clc clear close all% 参数设置 TBP 80; % 时间带宽积 T 10e-6; % 脉冲持续时间 N_ZD 60; % 零频点位于中点右侧的距离&#xff0c;P58% 参数计算 B TBP/T; …...

Android企业项目开发实训室建设方案

一 、系统概述 Android企业项目开发作为新一代信息技术的重点和促进信息消费的核心产业&#xff0c;已成为我国转变信息服务业的发展新热点&#xff1a;成为信息通信领域发展最快、市场潜力最大的业务领域。互联网尤其是移动互联网&#xff0c;以其巨大的信息交换能力和快速渗透…...

11_Redis经典五大类型源码及底层实现

Redis经典五大类型源码及底层实现 一、Redis数据类型的底层数据结构 SDS动态字符串双向链表压缩列表 zpilist哈希表 hashtable调表 skiplist整数集合 intset快速列表 quicklist紧凑列表 listpack 二、Redis源码地址 Github&#xff1a;https://github.com/redis/redis 三、…...

AWS WAF实战、优势对比和缺陷解决

文章目录 挑战和目标AWS WAF的优势AWS WAF的不足我是怎么做的?什么是比较好的AWS WAF设计? 笔者为了解决公司Web站点防御性问题&#xff0c;较为深入的研究AWS WAF的相关规则。面对上千万的冲突&#xff0c;笔者不得设计出一种能漂亮处理冲突数据WAF规则。 AWS WAF开发人员在…...

13,【设计模式】代理

代理 代理支持任意参数的简单代理实现 代理 代理的本质是函数指针 代理分为单播&#xff0c;多播&#xff0c;动态多播&#xff08;ue4中提出的&#xff09; 单播&#xff1a;在网络通信中&#xff0c;单播是一种一对一的通信方式 多播&#xff1a;在网络通信中&#xff0c;…...

基于IDEA使用maven创建hibernate项目

1、创建maven项目 2、导入hibernate需要的jar包 <!--hibernate核心依赖--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.4.1.Final</version></dependency><!--…...

使用Termux在安卓手机上搭建Hexo博客网站,并发布到公网访问

文章目录 1. 安装 Hexo2. 安装cpolar内网穿透3. 公网远程访问4. 固定公网地址 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并…...

宝塔 杀死 java服务 netstat -tlnp | grep :7003 kill 2205698

7003 是端口 netstat -tlnp | grep :7003 kill 2205698...

Python3 数据类型转换

Python3 数据类型转换 有时候&#xff0c;我们需要对数据内置的类型进行转换&#xff0c;数据类型的转换&#xff0c;一般情况下你只需要将数据类型作为函数名即可。 Python 数据类型转换可以分为两种&#xff1a; 隐式类型转换 - 自动完成显式类型转换 - 需要使用类型函数来…...

Cookie 和 Session 的工作流程

目录 一、Cookie是什么&#xff1f; 二、Session是什么? 三、Cookie的工作流程 四、Session的工作流程 五、Session和Cookie的区别和联系 一、Cookie是什么&#xff1f; Cookie是一种在网站和用户之间交换信息的机制。它是由Web服务器发送给用户浏览器的小型文本文件&#xff…...

AutoSAR配置与实践(基础篇)3.6 BSW的WatchDog功能

3.6 BSW的WatchDog功能 一、WatchDog功能介绍1.1 WatchDog 模块组成1.2 内外部看门狗区别和原理1.3 常见看门狗校验方式一、WatchDog功能介绍 1.1 WatchDog 模块组成 WatchDog 即看门狗功能。这个看门狗不是真正看家的狗,而是软件的一个模块,但是因为功能类似故以此起名。主…...

运维高级第6次作业

1.安装docker服务&#xff0c;配置镜像加速器 Docker安装与镜像加速器配置_ZRSAI的博客-CSDN博客 2.下载系统镜像&#xff08;Ubuntu、 centos&#xff09; 执行该命令后&#xff0c;Docker会自动从Docker Hub镜像库中下载Ubuntu镜像&#xff0c;并将其保存到本地计算机上: [ro…...

MongoDB使用GridFS存储大数据(Java)

MongoDB 是一个灵活的 NoSQL 数据库&#xff0c;能够存储大量的数据。但是&#xff0c;当涉及到特别大的数据项&#xff0c;比如大文件、视频或大型图片时&#xff0c;MongoDB 提供了一个特殊的方法来存储这些数据&#xff1a;GridFS。 简介&#xff1a; 1. 什么是 GridFS&am…...

内网穿透实战应用-windwos10系统搭建我的世界服务器,内网穿透实现联机游戏Minecraft

文章目录 1. Java环境搭建2.安装我的世界Minecraft服务3. 启动我的世界服务4.局域网测试连接我的世界服务器5. 安装cpolar内网穿透6. 创建隧道映射内网端口7. 测试公网远程联机8. 配置固定TCP端口地址8.1 保留一个固定tcp地址8.2 配置固定tcp地址 9. 使用固定公网地址远程联机 …...

pytorch基于ray和accelerate实现多GPU数据并行的模型加速训练

在pytorch的DDP原生代码使用的基础上&#xff0c;ray和accelerate两个库对于pytorch并行训练的代码使用做了更加友好的封装。 以下为极简的代码示例。 ray ray.py #codingutf-8 import os import sys import time import numpy as np import torch from torch import nn im…...

[蓝帽杯 2022 初赛]domainhacker

打开流量包&#xff0c;追踪TCP流&#xff0c;看到一串url编码 放到瑞士军刀里面解密 最下面这一串会觉得像base64编码 删掉前面两个字符就可以base64解码 依次类推&#xff0c;提取到第13个流&#xff0c;得到一串编码其中里面有密码 导出http对象 发现最后有个1.rar文件 不出…...

在 Pytorch 中使用 TensorBoard

机器学习的训练过程中会产生各类数据&#xff0c;包括 “标量scalar”、“图像image”、“统计图diagram”、“视频video”、“音频audio”、“文本text”、“嵌入Embedding” 等等。为了更好地追踪和分析这些数据&#xff0c;许多可视化工具应运而生&#xff0c;比如之前介绍的…...

Grafana Dashboard 备份方案

文章目录 Grafana Dashboard 备份方案引言工具简介支持的组件要求配置备份安装使用 pypi 安装grafana备份工具配置环境变量使用Grafana Backup Tool 进行备份恢复备份 Grafana Dashboard恢复 Grafana Dashboard结论Grafana Dashboard 备份方案 引言 每个使用 Grafana 的同学都…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...