背包小专题

背包小专题

  • 1. CF106C Buns
    • 题目描述
    • 题目概况
    • 思路点拨
    • 代码实现
  • 2. CF864E Fire
    • 题目描述
    • 题目概况
    • 思路点拨
    • 代码实现
  • 3. CF366C Dima and Salad
    • 题目描述
    • 题目概况
    • 思路点拨
      • 背包瓶颈
      • 解决方法
    • 代码实现
  • 4. CF1132E Knapsack
    • 题目描述
    • 题目概况
    • 思路点拨
    • 代码实现
  • 5. CF632E Thief in a Shop
    • 题目描述
    • 题目概况
    • 思路分析
      • 基本分析
      • 单一性反推多样性
      • 思想迸射
      • 思路一般化处理
    • 代码实现

1. CF106C Buns

题目描述

https://www.luogu.com.cn/problem/CF106C

题目概况

来源:Codeforces

洛谷难度: 黄题 \color{yellow}黄题 黄题

CF难度: 1700 1700 1700

标签: 01 背包 01背包 01背包

思路点拨

对于包子,包子的数量有上限 ⌊ a i b i ⌋ \lfloor \frac{a_i}{b_i}\rfloor biai 即特殊标记馅料数量比上一个 i i i 包子所需要的馅料数量。

一种包子的上限最多是 100 100 100, 面包的上限是 1000 1000 1000, 最多有 10 10 10 种包子,所以物品的上限是 2000 2000 2000 01 背包即可 01背包即可 01背包即可
时间复杂度 O ( 2000 ⋅ n ) ≈ 2 e 6 \Omicron(2000\cdot n)\approx 2e6 O(2000n)2e6
AC.

代码实现

#include<bits/stdc++.h>
using namespace std;const int maxn=50;
const int maxm=1e3+10;
int n,m,x,y,c,d,cnt;
int f[maxm][maxm];
struct node{int w,v;
}a[maxn*maxm];
inline void calculate(int num,int w,int v){int s=1;while(num){if(num>=s){a[++cnt].w=s*w;a[cnt].v=s*v;num-=s;}else {a[++cnt].w=num*w;a[cnt].v=num*v;num=0;}s*=2;}return ;
}
int main(){scanf("%d%d%d%d",&m,&n,&c,&d);calculate(1000,c,d);for(int i=1;i<=n;i++){scanf("%d%d%d%d",&x,&y,&c,&d);calculate(x/y,c,d);}
//	printf("%d\n",cnt);for(int i=1;i<=cnt;i++){for(int j=0;j<=m;j++){f[i][j]=f[i-1][j];if(j>=a[i].w)f[i][j]=max(f[i][j],f[i-1][j-a[i].w]+a[i].v);}}printf("%d\n",f[cnt][m]);return 0;
}

2. CF864E Fire

题目描述

https://www.luogu.com.cn/problem/CF864E

题目概况

来源:Codeforces

洛谷难度: 绿题 \color{green}绿题 绿题

CF难度: 2000 2000 2000

标签: 01 背包 01背包 01背包

思路点拨

对于 ∀ i \forall i i 都有时间上限为 d i − 1 d_{i}-1 di1, 01 背包 01背包 01背包 记录路径即可
时间复杂度 O ( max ⁡ d i ⋅ n ) ≈ 2 e 5 \Omicron(\max{d_{i}}\cdot n)\approx 2e5 O(maxdin)2e5
AC.

代码实现

#include<bits/stdc++.h>
using namespace std;const int maxn=100+10;
const int maxm=2e3+10;
int n,tot;
int ans[maxn];
int f[maxn][maxm];
int fa[maxn][maxm][3];
struct item{int t,d,p,op;inline void input(){scanf("%d%d%d",&t,&d,&p);}
}a[maxn];
inline bool cmp(item nx,item ny){return nx.d<ny.d;}
inline void calculate(int x,int y,int z){if(x==0){if(z==1)ans[++tot]=a[x+1].op;return ;}if(z==1)ans[++tot]=a[x+1].op;calculate(fa[x][y][0],fa[x][y][1],fa[x][y][2]);return ;
}
int main(){scanf("%d",&n);for(int i=1;i<=n;i++){a[i].input();a[i].op=i;}sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++){for(int j=0;j<a[i].d;j++){f[i][j]=f[i-1][j];fa[i][j][0]=i-1;fa[i][j][1]=j;fa[i][j][2]=0;if(j>=a[i].t){if(f[i][j]<f[i-1][j-a[i].t]+a[i].p){f[i][j]=f[i-1][j-a[i].t]+a[i].p;fa[i][j][0]=i-1;fa[i][j][1]=j-a[i].t;fa[i][j][2]=1; }} }}int s=0;for(int i=1;i<a[n].d;i++){if(f[n][i]>f[n][s])s=i;}printf("%d\n",f[n][s]);calculate(fa[n][s][0],fa[n][s][1],fa[n][s][2]);printf("%d\n",tot);reverse(ans+1,ans+tot+1);for(int i=1;i<=tot;i++)printf("%d ",ans[i]); return 0;
} 

3. CF366C Dima and Salad

题目描述

https://www.luogu.com.cn/problem/CF366C

题目概况

来源:Codeforces

洛谷难度: 蓝题 \color{blue}蓝题 蓝题

CF难度: 1900 1900 1900

标签: 01 背包 01背包 01背包

思路点拨

背包瓶颈

因为要使 ∑ a [ i ] = k ⋅ ∑ b [ i ] \sum a[i]=k \cdot \sum b[i] a[i]=kb[i] 这个条件看起来十分的恶心。

解决方法

令背包容量 p = a i − k ⋅ b i p=a_{i}-k\cdot b_{i} p=aikbi
p < 0 p<0 p<0 时扔入背包 f f f 的序列
p > = 0 p>=0 p>=0 时扔入背包 g g g 的序列
f [ i ] 、 g [ i ] f[i]、g[i] f[i]g[i] 均表示背包容量等于 i i i 的最大美味值
最终答案即为 max ⁡ ( f i + g i ) \max{(f_{i}+g_{i})} max(fi+gi) ,如果 ∀ f i 或 g i \forall f_{i} 或 g_{i} figi 都不成立,则答案为 − 1 -1 1
时间复杂度 O ( max ⁡ a [ i ] − k ⋅ b [ i ] ⋅ n 2 ) ≈ 1 e 6 \Omicron(\max{a[i]-k\cdot b[i]}\cdot n^2)\approx 1e6 O(maxa[i]kb[i]n2)1e6
AC.

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;const int maxn=100+10;
const int maxm=1e5+10;
const int inf=1e18;
int n,k,cnt1,cnt2;
int f[maxm],g[maxm],t[maxn];
struct node{int w,v;
}a[maxn],b[maxn];
signed main(){scanf("%lld%lld",&n,&k);for(int i=1;i<=n;i++)scanf("%lld",&t[i]);for(int i=1;i<=n;i++){int u;scanf("%lld",&u);int p=t[i]-k*u;if(p<=0){a[++cnt1].w=abs(p);a[cnt1].v=t[i];}else {b[++cnt2].w=p;b[cnt2].v=t[i];}}for(int i=1;i<=100000;i++)f[i]=g[i]=-inf;for(int i=1;i<=cnt1;i++){for(int j=100000;j>=a[i].w;j--)f[j]=max(f[j],f[j-a[i].w]+a[i].v);}for(int i=1;i<=cnt2;i++){for(int j=100000;j>=b[i].w;j--)g[j]=max(g[j],g[j-b[i].w]+b[i].v);}int ans=0;for(int i=0;i<=100000;i++)ans=max(ans,f[i]+g[i]);if(ans==0)ans=-1;printf("%lld\n",ans);return 0;
}

4. CF1132E Knapsack

题目描述

https://www.luogu.com.cn/problem/CF1132E

题目概况

来源:Codeforces

洛谷难度: 蓝题 \color{blue}蓝题 蓝题

CF难度: 2300 2300 2300

标签: 01 背包 01背包 01背包

思路点拨

将单个物品打成 840 840 840 的堆
W ≥ ∑ 1 8 c n t i ⋅ i W \geq \sum_1^8 cnt_{i}\cdot i W18cntii 则答案为 ∑ 1 8 c n t i ⋅ i \sum_1^8 cnt_{i}\cdot i 18cntii
否则 840 840 840 堆用完和未用完,剩余的数量不足 840 840 840,直接01

时间复杂度 O ( 1000 ∗ 840 ) ≈ 1 e 6 \Omicron(1000*840)\approx 1e6 O(1000840)1e6
AC.

代码实现

#include<bits/stdc++.h>
#define int long long 
using namespace std;const int maxn=20+10;
const int maxm=1e4+10;
const int maxk=1e3+10;
int w,s,cnt,tot;
int a[maxn],b[maxn],v[maxm],f[maxk];
signed main(){scanf("%lld",&w);s=w/840;for(int i=1;i<=8;i++){scanf("%lld",&a[i]);b[i]=a[i]/(840/i);a[i]=a[i]%(840/i);if(s>=b[i]){s-=b[i];b[i]=0;}else {b[i]-=s;s=0;}}for(int i=1;i<=8;i++){if(b[i]>0)a[i]=840/i;tot=tot+i*a[i];for(int j=1;j<=a[i];j++)v[++cnt]=i;}int p=w%840;if(s==0){for(int i=1;i<=cnt;i++){for(int j=p;j>=v[i];j--)f[j]=max(f[j],f[j-v[i]]+v[i]);}printf("%lld\n",w-(p-f[p]));}else {p=p+s*840;if(p>=tot)printf("%lld\n",w-(p-tot));else {for(int i=1;i<=cnt;i++){for(int j=p;j>=v[i];j--)f[j]=max(f[j],f[j-v[i]]+v[i]);}printf("%lld\n",w-(p-f[p]));}}return 0;
} 

5. CF632E Thief in a Shop

题目描述

https://www.luogu.com.cn/problem/CF632E

题目概况

来源:Codeforces

洛谷难度: 紫题 \color{purple}紫题 紫题

CF难度: 2400 2400 2400

标签: 01 背包 01背包 01背包

思路分析

基本分析

本题,可读出来每个物品可取无限次 -> 很像完全背包

但是,题目限定恰好取 k k k件物品,十分的恶心(同时也是提升的一次机会。
不妨可以看出这道题中件数是代价,而且每件物品的件数均为1(有点小别扭),所以每件物品的代价均为 1 1 1

单一性反推多样性

之前做的背包题普遍是靠代价推转移方程算价值,但 d p dp dp只会取极值存储,就如函数的单一性每个 x x x对应唯一的 y y y ,反之拿 y y y x x x是本题不错的选择,因为函数中每个 y y y可以对应多个不同的 x x x。我之所以用函数来解释 d p dp dp,是因为 d p dp dp本身就是函数
所以一个代价只能对应一个极端价值,但是一个价值能对应多个代价,取代价最小,这个价值的发展空间才能最大化。

思想迸射

一个不成熟的思路油然而生;
状态定义:定义 f i f_i fi当凑得价值为 i i i时,最小所花费的次数

思路一般化处理

先不说 f i f_i fi怎么转移,至少我们可以确定这个 f f f数组是没有后效性的。

假设我们有了一个处理好的数组 f f f,针对 ∀ i ( 1 ≤ i ≤ 100 0 2 ) \forall i(1 \leq i \leq 1000^2) i(1i10002)
f i = k f_i=k fi=k
∴ f i , 绝对可取 \therefore f_i ,绝对可取 fi,绝对可取
f i > k f_i>k fi>k
∴ f i ,绝对不可取 \therefore f_i,绝对不可取 fi,绝对不可取
但针对 f i < k f_i <k fi<k
我们不清楚是否能取到,我们需要用一些特殊的处理方式来处理一下。

还来下面将说明这道题,不看 t j tj tj在一个月内都想不出来的处理方法

  • 加入价值为0的物品( l i t t l e t r i c k little trick littletrick

因为这样在转移方程时,会忽略价值为 0 0 0的物品,加入它们不会让最小凑齐数最小。
∴ 为了让发展空间最大化,将 a 数组 s o r t ( 从小 − > 大 ) ,将 ∀ a i ( 1 ≤ i ≤ n ) − a 1 , 让原有 a 1 变为 0. 最后针对 f i < k 的情况将 i + k a 1 , 凑齐 k 件物品,将 i + k a 1 作为最终结果 \therefore 为了让发展空间最大化,将a数组sort(从小->大),将\forall a_i( 1 \leq i \leq n)-a_1,让原有a_1变为0.最后针对f_i<k的情况将i+ka_1,凑齐k件物品,将i+ka_1作为最终结果 为了让发展空间最大化,将a数组sort(从小>),将ai(1in)a1,让原有a1变为0.最后针对fi<k的情况将i+ka1,凑齐k件物品,将i+ka1作为最终结果

状态转移方程 f i = min ⁡ ( f i , min ⁡ ( f i − a j + 1 ) ) ) ( 1 ≤ i ≤ 100 0 2 ) ( 1 ≤ j ≤ n ) f_i=\min(f_i,\min(f_{i-a_j}+1)))(1 \leq i \leq 1000^2) (1 \leq j \leq n) fi=min(fi,min(fiaj+1)))(1i10002)(1jn)

时间复杂度: O ( 100 0 2 ⋅ n ) \Omicron(1000^2 \cdot n) O(10002n)
n 与 1000 同阶 n与1000同阶 n1000同阶
O ( n 3 ) ≈ 1 e 9 \Omicron(n^3) \approx 1e9 O(n3)1e9
5 s − > ≈ 1 e 9 5s -> \approx 1e9 5s>≈1e9
可以AC
分析结束!

代码实现

#include<bits/stdc++.h>
using namespace std;const int maxn=1e3+10;
const int inf=2e9;
int n,k,cnt;
int a[maxn],f[maxn*maxn],ans[2*maxn*maxn];
int main(){scanf("%d%d",&n,&k);for(int i=1;i<=1000000;i++)f[i]=inf;//状态初始化for(int i=1;i<=n;i++)scanf("%d",&a[i]);sort(a+1,a+n+1);//sort lower->upper//计算凑齐价值为i的最小件数for(int j=1;j<=n;j++){for(int i=a[j]-a[1];i<=1000000;i++){if(f[i-(a[j]-a[1])]==inf)continue;f[i]=min(f[i],f[i-(a[j]-a[1])]+1);//价值为0物品处理}}//f[i]<=k 对于价值物品的补助for(int i=0;i<=1000000;i++){if(f[i]<=k)ans[++cnt]=i+k*a[1];else continue;}//sort printsort(ans+1,ans+cnt+1);for(int i=1;i<=cnt;i++)printf("%d ",ans[i]);return 0;
}

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

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

相关文章

Leetcode 435 无重叠区间

题意理解&#xff1a; 给定一个区间的集合 intervals 要求需要移除区间&#xff0c;使剩余区间互不重叠 目标&#xff1a;最少需要移除几个区间。 解题思路&#xff1a; 采用贪心思路解题&#xff0c;什么是全局最优解&#xff0c;什么是局部最优解。 全局最优解&#xff0c;删…

使用Java语言判断一个年度是不是闰年

一、 代码说明 引入Scanner函数&#xff0c;将类命名为Judge类&#xff0c;使用try语句和catch语句将整体代码包围起来&#xff0c;使用if语句来判断是否为闰年&#xff0c;输入年份&#xff0c;然后得到相应的结论。 二、代码 import java.util.Scanner; public class Judg…

叮咚,微信年度聊天报告(圣诞节版)请查收~丨GitHub star 16.8k+

微信年度聊天报告——圣诞节特别版&#xff0c;快发给心仪的ta吧~ 开源地址 GitHub开源地址&#xff1a;https://github.com/LC044/WeChatMsg 我深信有意义的不是微信&#xff0c;而是隐藏在对话框背后的一个个深刻故事。未来&#xff0c;每个人都能拥有AI的陪伴&#xff0c;…

Microsoft Store 里有哪些好用的软件?

Windows 应用商店还是有不少干货软件的。 下面给大家推荐 12 款 Windows 应用商店里优秀实用的 UWP 应用软件&#xff0c;无广告、不流氓、体验好&#xff0c;强烈建议收藏&#xff01; 而且经过商店审核和限制&#xff0c;也更加安全、干净&#xff0c;不用担心有乱七八糟的…

内存管理学习

内存管理 在计算系统中&#xff0c;通常存储空间分为两种&#xff1a;内部存储空间和外部存储空间。 内部存储空间通常访问速度比较快&#xff0c;能够按照变量地址随机访问&#xff0c;也就是我们通常所说的RAM&#xff08;随机存储器&#xff09;&#xff0c;可以把它理解为…

Unity 问题 之 ScrollView ,LayoutGroup,ContentSizeFitter 一起使用时,动态变化时无法及时刷新更新适配界面的问题

Unity 问题 之 ScrollView ,LayoutGroup,ContentSizeFitter 一起使用时&#xff0c;动态变化时无法及时刷新更新适配界面的问题 目录 Unity 问题 之 ScrollView ,LayoutGroup,ContentSizeFitter 一起使用时&#xff0c;动态变化时无法及时刷新更新适配界面的问题 一、简单介绍…

Yolov5水果分类识别+pyqt交互式界面

Yolov5 Fruits Detector Yolov5 是一种先进的目标检测算法&#xff0c;可以应用于水果分类识别任务。结合 PyQT 框架&#xff0c;可以创建一个交互式界面&#xff0c;使用户能够方便地上传图片并获取水果分类结果。以下将详细阐述 Yolov5 水果分类识别和 PyQT 交互式界面的实现…

基于ssm智能社区管理系统的设计与实现+vue论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本智能社区管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

unity脚本API中OnCollisionEnter()、OnTriggerEnter()二者的区别

Unity中的OnCollisionEnter和OnTriggerEnter两个函数在日常的开发中很常见但也容易混淆&#xff0c;下面说一说两者的区别。 碰撞器&#xff08;Collider&#xff09;与触发器&#xff08;Trigger&#xff09;的概念 碰撞器&#xff08;Collider&#xff09;和触发器&#xff…

nodejs+vue+ElementUi医院预约挂号系统3e3g0

本医院预约挂号系统有管理员&#xff0c;医生和用户。该系统将采用B/S结构模式&#xff0c;使用Vue和ElementUI框架搭建前端页面&#xff0c;后端使用Nodejs来搭建服务器&#xff0c;并使用MySQL&#xff0c;通过axios完成前后端的交互 管理员功能有个人中心&#xff0c;用户管…

JAVA程序流程控制

程序的流程控制一般分为3种&#xff1a;顺序结构、分支结构、循环结构 顺序结构&#xff1a;就是不加任何控制&#xff0c;代码从main方法开始自上而下执行 分支结构&#xff1a;就是根据条件判断是true还是false&#xff0c;有选择性的执行哪些代码。在Java语言中提供了两个格…

人工智能_机器学习071_SVM支持向量机_人脸识别算法_LFW人脸数据加载_与理解---人工智能工作笔记0111

然后我们继续来看 这里有个lfw_home可以看到这个数据是,包含了人脸数据 然后我们继续看,在我们的顶你用户目录下,如果安装了,sklearn就会有这样一个目录, scikit_learn_data目录,这个里面可以看到 可以看到这个文件夹中有个 lfw_home文件夹是对.zip文件夹的解压,这个下载以后…

0.618算法和基于Armijo准则的线搜索回退法

0.618代码如下&#xff1a; import math # 定义函数h(t) t^3 - 2t 1 def h(t): return t**3 - 2*t 1 # 0.618算法 def golden_section_search(a, b, epsilon): ratio 0.618 while (b - a) > epsilon: x1 b - ratio * (b - a) x2 a ratio * (b - a) h_…

mybatis-plus阻止全表更新与删除

BlockAttackInnerInterceptor 是mybatis-plus的一个内置拦截器&#xff0c;用于防止恶意的全表更新或删除操作。当你添加了这个拦截器后&#xff0c;它会检查即将执行的 sql语句&#xff0c;如果有尝试进行全表更新或删除的语句&#xff0c;该拦截器会阻止这些操作。 <!-- m…

似然函数的定义:

似然函数&#xff08;Likelihood function&#xff09;是一个统计学中的概念&#xff0c;用于在给定某些数据的条件下&#xff0c;评估不同参数下模型生成这些数据的概率。在概率论和统计学中&#xff0c;似然函数是固定数据并视参数为变量的函数&#xff0c;而概率函数则是固定…

L1-058:6翻了

“666”是一种网络用语&#xff0c;大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”&#xff0c;意思是“6翻了”&#xff0c;实在太厉害的意思。如果你以为这就是厉害的最高境界&#xff0c;那就错啦 —— 目前的最高境界是数字“27”&#xff0c;因为这…

微信小程序 文件下载、打开、转发

一.下载文件 wx.downloadFile({url: https://img.haihaina.cn/月度支出表.xls, filePath: wx.env.USER_DATA_PATH / 自定义名字.xlsx,success(res) {console.log(downloadFile,res)const filePath res.tempFilePathwx.openDocument({filePath: filePath,fileType: xlsx,succe…

算法-两数之和

题目描述&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。…

openGauss学习笔记-168 openGauss 数据库运维-备份与恢复-导入数据-使用gs_restore命令导入数据

文章目录 openGauss学习笔记-168 openGauss 数据库运维-备份与恢复-导入数据-使用gs_restore命令导入数据168.1 操作场景168.2 操作步骤168.3 示例 openGauss学习笔记-168 openGauss 数据库运维-备份与恢复-导入数据-使用gs_restore命令导入数据 168.1 操作场景 gs_restore是…

【Linux】进程周边007之进程控制

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.进程创建 2.进程终止 2.…