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

XCPC第九站———背包问题!

在这里插入图片描述

1.01背包问题

在这里插入图片描述
        我们首先定义一个二维数组f,其中f[i][j]表示在前i个物品中取且总体积不超过j的取法中的最大价值。那么我们如何得到f[i][j]呢?我们运用递推的思想。由于第i个物品只有选和不选两种情况,当不选第i个物品时,f[i][j]=f[i-1][j],即取前i-1个物品且总体积小于等于j的所有取法中的最大价值;当选第i个物品时,我们要为第i个物品留出空间,此时f[i][j]=f[i-1][j-v[i]]+wi,即取前i-1个物品且总体积不能超过j-v[i]的取法中的最大价值再加上第i个物品的价值。因此代码如下:

#include<iostream>
#include<cmath>
using namespace std;
const int K = 1010;int v[K],w[K],f[K][K];int main()
{//本来应该对f[0][0~V]进行初始化为0,但由于我们开的数组是全局变量,自动初始化为0,因此这一步省略了。int N,V;cin>>N>>V;//一定要从下标1开始读入数据,因为后面是从下标1开始遍历物品的,如果从下标0开始读入,会遗漏第一个物品。for(int i = 1;i<=N;i++)  cin>>v[i]>>w[i];//由于i-1应该大于等于0,所以从i=1开始遍历。for(int i = 1;i<=N;i++){for(int j = 0;j<=V;j++){//只有在j>=v[i],即能放得下第i个物品的时候我们才有第二种情况。因此我们不妨直接先让f[i][j]继承f[i-1][j],然后再在满足条件时取两者中的最大值即可。f[i][j] = f[i-1][j];if(j>=v[i])f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);}}cout<<f[N][V]<<endl;return 0;
}

        那么我们如何对代码进行优化呢?我们能不能让f[j]表示总体积小于等于j的取法中的最大价值呢?答案是肯定的。请看代码——

#include<iostream>
#include<cmath>
using namespace std;
const int K = 1010;int v[K],w[K],f[K];int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++)  cin>>v[i]>>w[i];for(int i = 1;i<=N;i++)//这里省略了一行恒等式:f[j] = f[j]。这个式子的含义是,当j小于v[i]时,我们不能取第i个物品。//这里要从大到小遍历,是为了避免某个物品被重复取用。如图————for(int j = V;j>=v[i];j--)f[j] = max(f[j],f[j-v[i]]+w[i]);cout<<f[V]<<endl;return 0;
}

在这里插入图片描述
        在计算f[2]时,我们可以发现物品1被放进去了两次,这是不被允许的。会产生这样结果的原因是j - v[i]<j,那么f[j-v[i]]在该第i轮循环中已经被计算过,也就是说f[j-v[i]]的真实含义是f[i][j-v[i]],它的值已经被“污染”。但是对比上一份二维数组的代码,我们知道我们要的其实是f[i-1][j-v[i]]。而若倒序遍历,j-v[i]<j,遍历到j-v[i]在j之后,也就是说第i轮循环时j-v[i]还没有计算到,代码会利用第i-1轮循环的值来代替,这正合我们的心意。
        我们还可以优化输入,边输入边处理,这样就不用开额外的数组了。

#include<iostream>
#include<cmath>
using namespace std;const int K = 1010;
int f[K];int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++){int v,w;cin>>v>>w;for(int j = V;j>=v;j--)f[j] = max(f[j],f[j-v]+w);}cout<<f[V]<<endl;
}

2.完全背包问题

在这里插入图片描述
        我们仍然首先考虑朴素算法。像上一题一样,我们开一个f数组,其中f[i][j]表示在前i个物品中取且总体积不大于j的取法的最大价值。那么第i个物品可以取0,1,2,3……k个。第i个物品不能无限取,因为背包的容量是有限的。那么我们就有了递推式(这里kv[i]<=V且j-kv[i]>=0,因为j<=V,我们只需要让k*v[i]<=j)——

f[i][j] = max(f[i-1][j-0*v[i]]+0*w[i],f[i-1][j-1*v[i]]+1*w[i],……,f[i-1][j-k*v[i]]+k*w[i]);

代码如下——

#include<iostream>
#include<cmath>
using namespace std;const int K = 1001;
int f[K][K];int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++){int v,w;cin>>v>>w;for(int j = 0;j<=V;j++){for(int k = 0;k*v<=j;k++)f[i][j] = max(f[i][j],f[i-1][j-k*v]+k*w);}}cout<<f[N][V]<<endl;return 0;
}

        这样我们就用到了三层循环。但是这个方法在Acwing中是会爆TLE的,我们能不能通过观察减少循环次数呢?
在这里插入图片描述

        因此我们的代码可以被优化为——

#include<iostream>
#include<cmath>
using namespace std;const int K = 1001;
int f[K][K];int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++){int v,w;cin>>v>>w;for(int j = 0;j<=V;j++){if(j>=v)    f[i][j] = max(f[i-1][j],f[i][j-v]+w);//别忘了考虑j<v,即放不下第i个物品的情形else    f[i][j] = f[i-1][j];}}cout<<f[N][V]<<endl;return 0;
}

        优化成一维数组如下:

#include<iostream>
#include<cmath>
using namespace std;const int K = 1001;
int f[K];int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++){int v,w;cin>>v>>w;for(int j = v;j<=V;j++)//这里不需要倒序遍历,是因为我们要的本来就是f[i][j-v],就是在这一层被算过的.倒序反而会出错,因为j-v<j还没有在这一层被算过,因此会调用f[i-1][j-v],这不是我们想要的。f[j] = max(f[j],f[j-v]+w);}cout<<f[V]<<endl;return 0;
}

3.多重背包问题(朴素版)

在这里插入图片描述

#include<iostream>
using namespace std;const int K = 1010;
int f[K][K];int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++){int v,w,s;cin>>v>>w>>s;for(int j = V;j>=0;j--)for(int k = 0;k*v<=j&&k<=s;k++)f[i][j] = max(f[i][j],f[i-1][j-k*v]+k*w);}cout<<f[N][V]<<endl;return 0;
}

4.多重背包问题(二进制优化版)

在这里插入图片描述

        当我们尝试像3.一样对代码进行优化时,我们会发现一个问题,即f[i][j]不能直接由f[i][j-v]来表示。原因如下图(假设总体积不大于j时所有该物品都能被放进去)——
在这里插入图片描述
        我们会发现,f[i][j-v[i]]会多出来一项导致不能完全对齐。那么为什么在完全背包问题中不会出现这种情况呢?因为那里的物品时无限个的,制约物品个数的是j而不是s,所以可以对齐。那么我们该如何进行优化呢?这里介绍二进制优化的神奇方法。它的基本思想是按照2的整数次幂将物品分为若干组,每组只有取和不取两种情况。这样就转化成了一个01背包问题。那么这样的分法是否可以囊括所有可能的选择呢?请看——
在这里插入图片描述
        如果s是一般的数(不能被表示成2的幂乘的和)呢?
在这里插入图片描述
        下面让我们一起来看看具体的代码实现吧!

#include<iostream>
#include<cmath>
using namespace std;
//由于log2(2000)*1000 = 11000,我们开到15000。
const int K = 15000;
//processed_v、processed_w分别表示打包后的体积和价值。
int f[K],processed_v[K],processed_w[K];
//cnt为计数器,表示当前的组数。
int cnt = 0;int main()
{int N,V;cin>>N>>V;for(int i = 1;i<=N;i++){int v,w,s;cin>>v>>w>>s;int k = 1;while(k<=s){cnt++;processed_v[cnt] = k*v;processed_w[cnt] = k*w;s-=k;k*=2;}//如果有剩下,也要打包if(s>0){cnt++;processed_v[cnt] = s*v;processed_w[cnt] = s*w;}}//对打包后的物品做01背包问题。for(int i = 1;i<=cnt;i++)for(int j = V;j>=processed_v[i];j--)f[j] = max(f[j],f[j-processed_v[i]]+processed_w[i]);cout<<f[V]<<endl;return 0;
}

5.分组背包问题

在这里插入图片描述
以上就是本篇文章的全部内容啦!如果你感觉有帮助,请多多支持博主!

相关文章:

XCPC第九站———背包问题!

1.01背包问题 我们首先定义一个二维数组f&#xff0c;其中f[i][j]表示在前i个物品中取且总体积不超过j的取法中的最大价值。那么我们如何得到f[i][j]呢&#xff1f;我们运用递推的思想。由于第i个物品只有选和不选两种情况&#xff0c;当不选第i个物品时&#xff0c;f[i][j]f[i…...

【软考 系统架构设计师】论文范文④ 论基于构件的软件开发

>>回到总目录<< 文章目录 论基于构件的软件开发范文摘要正文论基于构件的软件开发 软件系统的复杂性不断增长、软件人员的频繁流动和软件行业的激烈竞争迫使软件企业提高软件质量、积累和固化知识财富,并尽可能地缩短软件产品的开发周期。 集软件复用、分布式对…...

spring-integration-redis中分布式锁RedisLockRegistry的使用

pom依赖&#xff1a;<!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.integ…...

城市通电(prim算法)

acwing3728 蓝桥杯集训每日一题 平面上遍布着 n 座城市&#xff0c;编号 1∼n。 第 i 座城市的位置坐标为 (xi,yi) 不同城市的位置有可能重合。 现在要通过建立发电站和搭建电线的方式给每座城市都通电。 一个城市如果建有发电站&#xff0c;或者通过电线直接或间接的与建…...

【动态规划】

动态规划1引言题目509. 斐波那契数70. 爬楼梯746. 使用最小花费爬楼梯小结53. 最大子数组和结语引言 蓝桥杯快开始了啊&#xff0c;自从报名后还没认真学过算法有(>﹏<)′&#xff0c;临时抱一下佛脚&#xff0c;一起学学算法。 题目 509. 斐波那契数 斐波那契数 &am…...

秒懂算法 | DP概述和常见DP面试题

动态(DP)是一种算法技术,它将大问题分解为更简单的子问题,对整体问题的最优解决方案取决于子问题的最优解决方案。本篇内容介绍了DP的概念和基本操作;DP的设计、方程推导、记忆化编码、递推编码、滚动数组以及常见的DP面试题。 01、DP概述 1. DP问题的特征 下面以斐波那…...

【C++提高编程】C++全栈体系(二十五)

C提高编程 第四章 STL- 函数对象 一、函数对象 1. 函数对象概念 概念&#xff1a; 重载函数调用操作符的类&#xff0c;其对象常称为函数对象函数对象使用重载的()时&#xff0c;行为类似函数调用&#xff0c;也叫仿函数 本质&#xff1a; 函数对象(仿函数)是一个类&…...

【云原生】k8s核心技术—集群安全机制 Ingress Helm 持久化存储-20230222

文章目录一、k8s集群安全机制1. 概述2. RBAC——基于角色的访问控制二、Ingress三、Helm1. 引入2. 使用功能Helm可以解决哪些问题3. 介绍4. 3个重要概念5. helm 版本变化6. helm安装及配置仓库7. 使用helm快速部署应用8. 自己创建chart9. 实现yaml高效复用四、持久化存储1.nfs—…...

【Linux】实现简易的Shell命令行解释器

大家好我是沐曦希&#x1f495; 文章目录一、前言二、准备工作1.输出提示符2.输入和获取命令3.shell运行原理4.内建命令5.替换三、整体代码一、前言 前面学到了进程创建&#xff0c;进程终止&#xff0c;进程等待&#xff0c;进程替换&#xff0c;那么通过这些来制作一个简易的…...

再获认可!腾讯安全NDR获Forrester权威推荐

近日&#xff0c;国际权威研究机构Forrester发布最新研究报告《The Network Analysis And Visibility Landscape, Q1 2023》&#xff08;以下简称“NAV报告”&#xff09;&#xff0c;从网络分析和可视化&#xff08;NAV&#xff09;厂商规模、产品功能、市场占有率及重点案例等…...

代码审计之旅之百家CMS

前言 之前审计的CMS大多是利用工具&#xff0c;即Seay昆仑镜联动扫描出漏洞点&#xff0c;而后进行审计。感觉自己的能力仍与零无异&#xff0c;因此本次审计CMS绝大多数使用手动探测&#xff0c;即通过搜索危险函数的方式进行漏洞寻找&#xff0c;以此来提升审计能力&#xf…...

ONLYOFFICE中利用chatGPT帮助我们策划一场生日派对

近日&#xff0c;人工智能chatGPT聊天机器人爆火&#xff0c;在去年年底发布后&#xff0c;仅仅两个月就吸引了全球近一亿的用户&#xff0c;成为史上最快的应用消费程序&#xff0c;chatGPT拥有强大的学习和交互能力 可以被学生&#xff0c;教师&#xff0c;上班族各种职业运…...

Java面试题-线程(一)

在典型的 Java 面试中&#xff0c; 面试官会从线程的基本概念问起&#xff0c; 如&#xff1a;为什么你需要使用线程&#xff0c;如何创建线程&#xff0c;用什么方式创建线程比较好&#xff08;比如&#xff1a;继承 thread 类还是调用 Runnable 接口&#xff09;&#xff0c;…...

一篇普通的bug日志——bug的尽头是next吗?

文章目录[bug 1] TypeError: method object is not subscriptable[bug 2] TypeError: unsupported format string passed to numpy.ndarray.__format__[bug 3] ValueError:Hint: Expected dtype() paddle::experimental::CppTypeToDataType<T>::Type()[bug 4] CondaSSLE…...

Vue 3 第八章:Watch侦听器

文章目录Watch侦听器1. 基础概念1.1. Watch的基本用法例子1&#xff1a;监听单个ref的值&#xff0c;直接监听例子2&#xff1a;监听多个ref的值&#xff0c;采用数组形式例子3&#xff1a;深度监听例子4&#xff1a;监听reactive响应式对象单一属性&#xff0c;采用回调函数的…...

GlassFish的安装与使用

一、产品下载与安装glassfish下载地址&#xff1a;https://download.oracle.com/glassfish/5.0.1/release/index.html下载后解压即完成安装&#xff0c;主要目录说明&#xff1a;bin目录&#xff1a;为asadmin命令所在目录。glassfish为主目录&#xff1a;glassfish\bin目录为命…...

【java】Java 重写(Override)与重载(Overload)

文章目录重写(Override)方法的重写规则Super 关键字的使用重载(Overload)重载规则实例重写与重载之间的区别总结重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变&#xff0c;核心重写&#xff01; 重写的好处在于…...

OpenCV-PyQT项目实战(12)项目案例08:多线程视频播放

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列&#xff0c;持续更新中 OpenCV-PyQT项目实战&#xff08;1&#xff09;安装与环境配置 OpenCV-PyQT项目实战&#xff08;2&#xff09;QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战&#xff08;3&#xff09;信号与槽机制 …...

面向对象设计模式:结构型模式之装饰器模式

文章目录一、引入二、装饰器模式2.1 Intent 意图2.2 Applicability 适用性2.3 类图2.4 优缺点2.5 应用实例&#xff1a;Java IO 类2.6 应用实例&#xff1a;咖啡馆订购系统一、引入 咖啡馆订购系统 Initial 初始 4 种咖啡 House blend (混合咖啡)Dark Roast (深度烘培)Decaf (…...

Unity iOS 无服务器做一个排行榜 GameCenter

排行榜需求解决方案一(嗯目前只有一)UnityEngine.SocialPlatformsiOS GameCenterAppStoreConnect配置Unity 调用(如果使用GameCenter系统的面板&#xff0c;看到这里就可以了&#xff09;坑(需要获取数据做自定义面板的看这里)iOS代码Unity 代码吐槽需求 需求&#xff1a;接入…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

高抗扰度汽车光耦合器的特性

晶台光电推出的125℃光耦合器系列产品&#xff08;包括KL357NU、KL3H7U和KL817U&#xff09;&#xff0c;专为高温环境下的汽车应用设计&#xff0c;具备以下核心优势和技术特点&#xff1a; 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计&#xff0c;确保在…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...

Linux中INADDR_ANY详解

在Linux网络编程中&#xff0c;INADDR_ANY 是一个特殊的IPv4地址常量&#xff08;定义在 <netinet/in.h> 头文件中&#xff09;&#xff0c;用于表示绑定到所有可用网络接口的地址。它是服务器程序中的常见用法&#xff0c;允许套接字监听所有本地IP地址上的连接请求。 关…...