bzoj2448 挖油
2448: 挖油
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 140 Solved: 61
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
8 24 12 6
Sample Output
HINT
对于100%的数据,n<=2000,ti<=10^6
Source
2011福建集训
分析:个人认为比较神的一道题,如果之前没有接触过这类题根本无从下手的那种.
做这道题之前可以先做一下poj3783,都是要使得最大值最小,猜答案的那种.
想法还是dp,能不能直接拿poj3783的状态来用呢?显然不行,这道题的答案和编号还是有关的,而poj3783是无关的.
类似的分析方法:先考虑在一个点k钻井,因为要使得结果最坏,如果k不是两个区间的端点,都不能知道答案,需要继续.这个时候就有两种选择了:1.往左. 2.往右. 每次取max,直到到达边界. 这个过程很像区间dp,有左右端点的限制嘛.那么令f[i][j]表示区间
[i,j]最坏情况下需要的最少时间.转移就是枚举一个点k,f[i][j] = min{max{f[i][k - 1],f[k + 1][j]} + a[k]}. 初始化f[i][i] = a[i].
这个dp的想法就是每次考虑当前钻哪个井,结果最坏就必须要钻其它位置的井,由此来扩展,取max是为了得到最坏情况.
区间dp一般都是O(n^3)的,这道题也不例外. 怎么优化呢?括号内的max限制了f[i][j]从哪个状态转移过来.如果没有了max,方程就变成了一个递推式.
考虑如何去掉max.可以发现当k大到一定程度的时候,f[i][k - 1]一定大于f[k + 1][j]的,那么就只会从f[i][k - 1]转移过来,因为f[i][k - 1]随着k的增大是单调不减的,所以可以用很多效率高的方法维护,一个比较好的方法就是单调队列. 每次将f[i][k-1]和a[k]的整体存到单调队列中,弹出最小值即可. 对于j也一样.
现在的问题是如何找到这个分界点.一个结论:区间[i,j + 1]的分界点一定在区间[i,j]的分界点右边,或者相同.这个挺好想的,因为左右两边的转移实际上是一种竞争关系嘛,如果分界点不增加,那么右边的值就会增大. 分界点的位置是单调的了,那么固定i,枚举j的时候,分界点也是在右移的,只需要维护一个指针表示分界点的位置就好了. 如果左边决策比不上右边决策,则指针往右.
上面考虑的是固定i,每次从左区间转移的答案. 固定j也是一样的,只是变成了指针向左扫. 这样的话有一个问题:每枚举到1个i,就要从i+1到n枚举j,难道每次都要清空优先队列吗? 不需要!
区间dp为了先处理得到小区间的值,倒序枚举i,顺序枚举j,对于j的单调队列不需要清空(i只会从上一个i的位置向左移动),为了避免重复占用同一个单调队列,开n个单调队列,而对于i的则必须清空了. 用一个单调队列维护固定i的答案,n个单调队列维护固定j的答案,总共就是n+1个单调队列了.
Question:单调队列维护的都是队首元素最小的队列. 最后的答案也是在两个单调队列中取min.那为什么没有max呢? 因为max只是决定了从哪个状态转移而来,最后对答案有影响的主要还是取min的部分,取max的部分在维护两个指针的过程中已经考虑了.
这类题型要熟记,对于决策会有分界点的dp优化也要熟练掌握.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int maxn = 2010; int n,a[maxn],f[maxn][maxn],l[maxn],r[maxn],q[maxn][maxn];int cal1(int x,int y,int z) {return f[x][z - 1] + a[z]; }int cal2(int x,int y,int z) {return f[z + 1][y] + a[z]; }int main() {memset(f,127/3,sizeof(f));scanf("%d",&n);for (int i = 1; i <= n; i++)scanf("%d",&a[i]);for (int i = n; i >= 1; i--){f[i][i] = a[i];l[0] = 0;r[0] = 1;q[0][++r[0]] = i;for (int j = i + 1; j <= n; j++){while (l[0] <= r[0] && cal1(i,j,q[0][l[0]]) < cal2(i,j,q[0][l[0]])) //这实际上就是维护一个指针l[0]++;while (l[0] <= r[0] && cal1(i,j,j) < cal1(i,j,q[0][r[0]]))r[0]--;q[0][++r[0]] = j;while (l[j] <= r[j] && cal2(i,j,q[j][l[j]]) < cal1(i,j,q[j][l[j]]))l[j]++;while (l[j] <= r[j] && cal2(i,j,i) < cal2(i,j,q[j][r[j]]))r[j]--;q[j][++r[j]] = i;f[i][j] = min(cal1(i,j,q[0][l[0]]),cal2(i,j,q[j][l[j]]));}}printf("%d\n",f[1][n]);return 0; }
转载于:https://www.cnblogs.com/zbtrs/p/8491115.html
bzoj2448 挖油相关推荐
- BZOJ 2448: 挖油
Description [0,x]中全是1,其余全是0,每个点有一个权值,求最坏情况下得到x的最小权值. Sol DP+单调队列. 首先就是一个 \(O(n^3)\) 的DP. \(f[i][j]\) ...
- BZOJ 2448: 挖油-区间DP+单调队列
题意: [0,x]中全是1,判断[1,n]中的点i中是0还是1需要权值aiaia_i,最坏情况下求得到x的最小权值 n<=2000n<=2000n Solution: f[i][j]f[i ...
- 【QBXT】学习笔记——Day3/4图论+dp
继续上传一波笔记吧. Day3 1.16AM 今天讲图论,以习题为主. 开篇水题: 给一幅图,若删去一个点后变成一棵树,则这个点合法.问哪些点合法. 思路根据树的性质:这个点不是割点,m-这个点的度数 ...
- 强化学习笔记5:learningplanning, explorationexploitation
1 learning & planning Learning 和 Planning 是序列决策的两个基本问题. 在强化学习中,环境初始时是未知的,agent 不知道环境如何工作,agent 通 ...
- 第一章 强化学习介绍
Reinforement Learning Reinforcement Learning 强化学习讨论的问题是一个 智能体(agent) 怎么在一个复杂不确定的环境(environment)里面去极大 ...
- Java面试一百道题目(第一题)-什么是面向对象,谈谈你对面向对象的理解
Java面试一百道题目(第一题) 1,什么是面向对象,谈谈你对面向对象的理解. 思路:用面向过程和面向对象做对比来突出什么是面向对象. 答:高级语言分为,面向对象语言和面向过程语言,面向过程语言,距离 ...
- python导入word转换的html,python如何转换word格式、读取word内容、转成html
# python如何转换word格式.读取word内容.转成html? import docx from win32com import client as wc # 首先将doc转换成docx wo ...
- Reinforement Learning-chapter1
Reinforement Learning Reinforcement Learning [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sG1oATCa-1603206 ...
- Altium Designer AD绘制放置中间挖空无覆铜绿油的mark点
最近因为项目的需要要用到开钢网,所以就查了查有关ad软件上的钢网教程.但是发现大部分教程只是通过修改焊盘,而没有办法实现焊盘周围挖空去除绿油.所以和大家分享记录一下这个方法. 第一步 在需要放置mar ...
最新文章
- php 下划线转大写开头,使用PHP把下划线分隔命名的字符串 转换成驼峰式命名方式 , 把下划线后面的第一个字母变成大写...
- Adobe Dreamweaver CS3中文版
- openssl 证书生成手册
- servlrt程序的入口点是_刚刚,微信偷偷更新,小程序又放大招了!
- 大数据 智能交通调度_大数据技术在智能交通中的应用
- SAP 电商云 Spartacus UI B2B checkout 点击 Continue 不能跳转到下一页面
- 小程序在wxml页面中取整
- 知识图谱发展的三个时期以及事理图谱概念辨析
- java 展现层框架_spring快速入门例子教程:06展现层
- Juniper防火墙备份与恢复处理方法
- 命令窗口ping oracle,Oracle中tnsping命令解析
- 1.java数组教程及示例知乎
- RENIX软件OSPF和BFD、ISIS和BFD联动测试——网络测试仪实操
- C++坦克大战源代码
- android国际化多语言对照
- Java多线程系列--“JUC集合”08之 LinkedBlockingQueue
- 如何在Ubuntu MATE 18.04中安装GNOME 3?
- 判断时间复杂度和空间复杂度
- 四川理工计算机专业好不好,急!!!!四川理工 、 宜宾学院 、 内江师范学院 哪个学校计算机专业好点?...
- 【FCN】Fully Convolutional Networks for Semantic Segmentation学习