【单调队列】【P1776】宝物筛选
Description
终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了……小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为\(W\)的采集车,洞穴里总共有n种宝物,每种宝物的价值为\(v_i\),重量为\(w_i\),每种宝物有\(m_i\)件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。
Input
第一行为一个整数\(N\)和\(w\),分别表示宝物种数和采集车的最大载重。
接下来\(n\)行每行三个整数,其中第\(i\)行第一个数表示第\(i\)类品价值,第二个整数表示一件该类物品的重量,第三个整数为该类物品数量。
Output
输出仅一个整数\(ans\),表示在采集车不超载的情况下收集的宝物的最大价值。
Sample Input
4 20
3 9 3
5 9 1
9 4 2
8 1 3
Sample Output
47
Hint
\(1~\leq~n~\leq~100\)
\(1~\leq~w~\leq~40000\)
数据保证合法
Solution
多重背包问题。设\(f_{i,j}\)是前\(i\)个物品重量是\(j\)的最大价值。考虑转移。朴素方法在转移时枚举该物品使用多少个。由于物品个数与\(w\)同阶,所以时间复杂度是\(O(nm^2)\),其中\(m\)代表最大载重量。
考虑优化。
考虑对第\(i\)个物品,重量为\(j\)时只能从\(j~-~k~\times~w_i\)转移。其中\(w\)代表重量。由于是连续转移,所以被转移的状态一定是单调不降的。考虑使用单调队列优化。
按照\(j~Mod~w_i\)分类,同一类之间才能转移,维护一群单调队列。每次判断出队时把队首元素加上在这个位置应该加的价值再与当前元素比较。
while((front <= end) && ((frog[pos][que[end]]+(k-que[end])/b*a)) <= frog[pos][k]) --end;
这里\(k\)是当前枚举到的背包重量。\(a\)是价值,\(b\)是该物品的重量。
同时,也可以不选择该物品,所以枚举所有重量与从上一行继承进行转移。
for(rg int j=1;j<=w;++j) frog[cur][j]=mmax(frog[cur][j],frog[pos][j]);
代码如下
Code
#include<cstdio>
#define rg register
#define ci const int
#define cl const long long int
typedef long long int ll;
namespace IO {
char buf[90];
}
template<typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while(ch>'9'||ch<'0') lst=ch,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst=='-') x=-x;
}
template<typename T>
inline void write(T x,const char aft,const bool pt) {
if(x<0) x=-x,putchar('-');
int top=0;
do {
IO::buf[++top]=x%10+'0';
x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}
template<typename T>
inline T mmax(const T a,const T b) {if(a>b) return a;return b;}
template<typename T>
inline T mmin(const T a,const T b) {if(a<b) return a;return b;}
template<typename T>
inline T mabs(const T a) {if(a<0) return -a;return a;}
template<typename T>
inline void mswap(T &a,T &b) {
T temp=a;a=b;b=temp;
}
const int maxn = 110;
const int maxm = 500010;
int n,w,cur,pos=1,front,end,a,b,c,ans;
int frog[2][maxm],que[maxm];
int main() {
qr(n);qr(w);
for(rg int i=1;i<=n;++i) {
a=b=c=0;qr(a);qr(b);qr(c);
rg int upceil=b*c;
for(rg int j=0;j<b;++j) {
que[front=end=1]=j;
for(rg int k=j+b;k<=w;k+=b) {
while((front <= end) && ((k-que[front]) > upceil)) ++front;
while((front <= end) && ((frog[pos][que[end]]+(k-que[end])/b*a)) <= frog[pos][k]) --end;
que[++end]=k;
frog[cur][k]=frog[pos][que[front]]+(k-que[front])/b*a;
}
}
for(rg int j=1;j<=w;++j) frog[cur][j]=mmax(frog[cur][j],frog[pos][j]);
mswap(cur,pos);
}
for(rg int i=1;i<=w;++i) ans=mmax(ans,frog[pos][i]);
write(ans,'\n',true);
return 0;
}
Summary
在使用手写队列时,初始化\(que[front=end=1]=0\)。判断队列不为空的条件是\(front ~\leq~end\)
【单调队列】【P1776】宝物筛选的更多相关文章
- P1776 宝物筛选_NOI导刊2010提高(02)&& 多重背包二进制优化
多重背包, 要求 \(N\log N\) 复杂度 Solution 众所周和, \(1-N\) 之内的任何数可以由 \(2^{0}, 2^{1}, 2^{2} ... 2^{\log N}, N - ...
- 洛谷P1776 宝物筛选_NOI导刊2010提高(02)
P1776 宝物筛选_NOI导刊2010提高(02) 题目描述 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎.但是这里的宝物实在是太多了, ...
- [luogu P1776] 宝物筛选 解题报告(单调队列优化DP)
题目链接: https://www.luogu.org/problemnew/show/P1776 题目: 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF ...
- 洛谷P1776 宝物筛选_NOI导刊2010提高(02)(多重背包,单调队列)
为了学习单调队列优化DP奔向了此题... 基础的多重背包就不展开了.设\(f_{i,j}\)为选前\(i\)个物品,重量不超过\(j\)的最大价值,\(w\)为重量,\(v\)为价值(蒟蒻有强迫症,特 ...
- 洛谷P1776 宝物筛选
一道很好的单调队列优化多重背包入门题 令\(v[i]\)表示重量,\(w[i]\)表示价格 ,\(c[i]\)表示最多可放的数量,不难推出朴素的转移方程如下: \(f[i][j]=max\{f[i-1 ...
- luogu||P1776||宝物筛选||多重背包||dp||二进制优化
题目描述 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎.但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物.看来小FF只能含泪 ...
- luogu P1776 宝物筛选_NOI导刊2010提高(02)
Sto flashhu orz flash太强啦 多重背包裸题(逃 使用压维大法,\(f_i\)为总重量为\(i\)时的答案 对于每种物品,记\(w\)为单个的重量,\(v\)为单个的价值,\(m\) ...
- P1776 宝物筛选_NOI导刊2010提高(02)
题目描述 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎.但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物.看来小FF只能含泪 ...
- P1776 宝物筛选_NOI导刊2010提高(02)(背包的二进制优化)
题目描述 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎.但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物.看来小FF只能含泪 ...
- 洛谷p1776宝物筛选
宝物筛选 多重背包问题 物品数目已知 可以枚举每个物品 当做01背包来做 不过会超时 此时需要二进制拆分来优化 分解成新的物品 再跑一遍01背包即可 //二进制拆分+01背包 //设f[j]表示前i件 ...
随机推荐
- 第三篇 JavaScript基础
知识预览 BOM对象 DOM对象(DHTML) 实例练习 转:https://www.cnblogs.com/yuanchenqi/articles/5980312.html#_label2 一.Ja ...
- 第三十九篇 Python异常处理
一. 什么是异常 异常就是程序运行时发生的错误,在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止,在python中,错误触发的异常如下 错误分成两种: #语法 ...
- 前端开发工程师 - 02.JavaScript程序设计 - 第1章.基础篇
第1章--基础篇 JS介绍 html 网页的内容:css 网页的样式:javascript 网页的行为 i.e. hello world <!DOCTYPE html> <html& ...
- django 与 flask里面从已有数据库表中反向生成models
django: 配置好数据库连接 python manage.py inspectdb > models.py 即可反向生成orm使用的models, 注意: > 后面可以定义为指定路 ...
- TW实习日记:第19天
今天一早上改完信息门户的代码之后,发现接口又出了问题,查了半天都不知道,原来又是网端的问题...真是心累啊,调整了一些细节样式,以及终于把企业微信的消息推送功能做完了.关键就在于有个表存放微信id的字 ...
- 剑指offer-从上往下打印二叉树22
题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. class Solution: # 返回从上到下每个节点值列表,例:[1,2,3] def PrintFromTopToBottom( ...
- POJ 3384 Feng Shui(计算几何の半平面交+最远点对)
Description Feng shui is the ancient Chinese practice of placement and arrangement of space to achie ...
- Internet History
Alan Turing and Bletchley Park Top secret breaking effort(二战破译希特勒密码) 10,000 people at the peak(team ...
- P4语法(2) Parser
这里参考学习了: P4语言规范 P4台湾社群 Parser 关于parser 在P4程序中,有着大量的首部(header)和首部实例,但每次只有部分首部实例会对数据包进行操作,而parser会用于生成 ...
- 理解windows模型
同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等).但是一般而言,我们在说同步.异步的时候,特指 ...