dp单调性优化
跟着书上的思路学习dp的单调性优化觉得还是很容易想的。

数据范围:

dp,数据范围是百万,这应该是O(n)的算法了。
首先不难想到设f[i]表示到第i个百米所能达到的最大能量,那么f[n]即为所求。
f[i]=max(f[i],f[j]+s[i]-s[j]-cost[i]);这个地方s数组是能量的前缀和,然后发现需要多加一层循环来枚举j,这个时候就是O(n^2)的算法了。
这样的话,就只有40分了,毕竟看分做题。这分给的还是很良心的。
考虑优化首先我们发现状态转移方程可以这样变f[i]=max{f[j]-s[j]}+s[i]-cost[i];我们这需要找到一个最大的f[j]-s[j]的即可
且f[j]还必须>=cost[i];因为这是判断能否调到也就是一个状态合法与否。
这样我们就可以维护一个双端队列来维护了!队首永远最优至于合法否我们需要小小的判断一下。
#include<bits/stdc++.h>
#include<iomanip>
#include<iostream>
#include<ctime>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#include<cstdlib>
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
if(x==){putchar('');putchar('\n');return;}
if(x<){putchar('-');x=-x;}
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=;
int v[MAXN],cost[MAXN];
int f[MAXN];//f[i]表示前i百米所能得到的最大能量
int q[MAXN],h=,t=;
int n,m;
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();f[]=m;
for(int i=;i<=n;i++)
{
v[i]=read();
cost[i]=i*;
v[i]+=v[i-];
}
q[h]=;
for(int i=;i<=n;i++)
{
while(f[q[h]]<cost[i])h++;//题目中给出保证一定能吃完,所以这个地方不需要加h<t
f[i]=f[q[h]]-cost[i]-v[q[h]]+v[i];
while(f[q[t]]-v[q[t]]<f[i]-v[i])t--;
q[++t]=i;
}
put(f[n]);
return ;
}
显然成功了呢,复杂度就是O(n)因为每个点进出队伍一次。

对于这个题目,我竟然直接手残翻开了书,看到了状态转移方程式。哎,自己没想。
其实状态转移方程也很好想,状态设为:f[i][j]表示第i个月存仓j个零件所得到的最低成本。
由此可得,f[i][j]=min{f[i-1][k]+(u[i]+j-k)*d[i]+m*k}其中j<=s,k<=j+u[i].(显然你不能把上个月的零件卖了)
由于k这个决策也需要枚举所以复杂度是O(n*s*s)的,s那么大这肯定炸啊。预期得分也是40。
搞一下优化,大括号里得到貌似都和k有关不如先展开再说。
f[i][j]=min{f[i][k]+(m-d[i])*k}+(u[i]+j)*d[i];这样的话只有f[i][k]和(m-d[i])*k和当前决策有关了,考虑维护一个最优决策那不就可以直接进行转移了么
这样的话就是O(n*s)的啊,能A。所以考虑维护一个单调队列,等等为什么要维护队列,队列中的其他值有用么,发现只要k属于它应该属于的范围之内的话,那么这个决策就一定是合法的,所以为什么要队列,直接一个值保存即可,这样每次和生成出来的值比较哪个更小不就有了最优解么。
这里就大功告成了,乌拉。
#include<bits/stdc++.h>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
if(x==){putchar('');putchar('\n');return;}
if(x<)x=-x,putchar('-');
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
while(num)putchar(ch[num--]);
}
const int MAXN=;
int n,m,s,p=;
int u[MAXN],d[MAXN];
int f[][];//f[i][j]表示第i个月保存j个商品所需最小费用。
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();s=read();
for(int i=;i<=n;i++)u[i]=read();
for(int i=;i<=n;i++)d[i]=read();
memset(f,,sizeof(f));
f[p][]=;
for(int i=;i<=n;i++)
{
p=p^;
int k=,ans=;
for(int j=;j<=s;j++)//枚举保存多少个商品
{
for(;k<=min(j+u[i],s);k++)//提供状态转移
//为什么最优的状态一定是ans呢?
//考虑到需要一个k值使ans最小且合法,合法那一定是<=min(j+u[i],s)
//得到ans就是最优的了,很显然吧,复杂度为n*s
ans=min(ans,f[p^][k]+(m-d[i])*k);
f[p][j]=ans+(u[i]+j)*d[i];
}
}
put(f[p][]);
return ;
}
显然的,我们发现当前状态只和上一个状态有关所以可以开滚动数组优化空间啊。这点完美意识还是需要的。
那么经过这两道题,相信单调性优化都了解的差不多了。可以深入学习一些其他优化了呢。
dp单调性优化的更多相关文章
- dp 单调性优化总结
对于单调性优化其实更多的是观察dp的状态转移式子的单调性 进而用优先队列 单调队列 二分查找什么的找到最优决策 使时间更优. 对于这道题就是单调性优化的很好的例子 首先打一个暴力再说. f[i][j] ...
- [NOI2009]诗人小G(dp + 决策单调性优化)
题意 有一个长度为 \(n\) 的序列 \(A\) 和常数 \(L, P\) ,你需要将它分成若干段,每 \(P\) 一段的代价为 \(| \sum ( A_i ) − L|^P\) ,求最小代价的划 ...
- Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...
- CF868F Yet Another Minimization Problem 分治决策单调性优化DP
题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...
- BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】
Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...
- 2018.10.14 NOIP训练 猜数游戏(决策单调性优化dp)
传送门 一道神奇的dp题. 这题的决策单调性优化跟普通的不同. 首先发现这道题只跟r−lr-lr−l有关. 然后定义状态f[i][j]f[i][j]f[i][j]表示猜范围为[L,L+i−1][L,L ...
- 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)
传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...
- 单调性优化DP
单调性优化DP Tags:动态规划 作业部落链接 一.概述 裸的DP过不了,怎么办? 通常会想到单调性优化 单调队列优化 斜率优化 决策单调性 二.题目 [x] 洛谷 P2120 [ZJOI2007] ...
- [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)
第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...
随机推荐
- elasticsearch中 refresh 和flush区别【转】
elasticsearch中有两个比较重要的操作:refresh 和 flush refresh操作 当我们向ES发送请求的时候,我们发现es貌似可以在我们发请求的同时进行搜索.而这个实时建索引并可以 ...
- java实现urlencode
https://www.cnblogs.com/del88/p/6496825.html ****************************************************** ...
- SaaS产品成功学
『精益』和『敏捷』之类的方法论在产品实现方面消除了不少浪费,但面对SaaS产品,这些却并没有像银弹般有效. 国外的『Ramen』团队模仿Maslow的需求层次理论提出了SaaS产品的需求层次理论,可以 ...
- Mysql 地区经纬度 查询
摘要: Mysql数据库,根据地区的经纬度信息,查询附近相邻的地区 2015-03-27 修改,增加 MySQL的空间扩展(MySQL Spatial Extensions)的解决方案: MySQL的 ...
- 仿迅雷播放器教程 -- 基于VLC的C++播放器 (4)
经过前面的介绍,想必大家对VLC和ffmpeg都有一定印象了,还记得学习ffmpeg多么蛋疼吗?那么VLC会不会也这么蛋疼呢? 那么我们来看一段官方的Demo,Alberl精简了Demo,只留 ...
- oracle 数据库对于多列求最大值
1.案例: SELECT GREATEST('36', '55', '34') V_MAX, LEAST('36', '55', '34') V_MIN FROM DUAL Oracle比较一列的最大 ...
- 试一下Markdown
Markdown 没想到博客园居然能够有markdown这样的写法了,以前觉得有自定义CSS已经非常不错了,现在居然加入Markdown,太值得称赞了.国内的博客系统,应该首屈一指了. 强调 你要走, ...
- 深度学习之windows安装tensorflow
1. 安装python3.5 2. 下载tensorflow-1.1.0rc2-cp35-cp35m-win_amd64.whl 3. pip install tensorflow-1.1.0rc2- ...
- 题目1015:还是A+B(简单判断)
题目链接:http://ac.jobdu.com/problem.php?pid=1015 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- 序列化模块和sys模块
sys模块 sys模块是与python解释器交互的一个接口 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys. ...