2448: 挖油

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 140  Solved: 61
[Submit][Status][Discuss]

Description

给出一条线段,在左端点点0与右端点n+1间有n个点(n<=2000),并且在0到x之间的所有点都是有油的,在每个点钻井判断是否有油需要时间ti,求能够知道x的最坏情况下最少需要多少时间。

Input

第一行包含一个数n,如题目描述。
第二行包含n个数,表示在第i个点钻井判断是否有油需要的时间。

Output

输出包含一行,最坏情况下最少需要多少时间。

Sample Input

4
8 24 12 6

Sample Output

42

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 挖油相关推荐

  1. BZOJ 2448: 挖油

    Description [0,x]中全是1,其余全是0,每个点有一个权值,求最坏情况下得到x的最小权值. Sol DP+单调队列. 首先就是一个 \(O(n^3)\) 的DP. \(f[i][j]\) ...

  2. BZOJ 2448: 挖油-区间DP+单调队列

    题意: [0,x]中全是1,判断[1,n]中的点i中是0还是1需要权值aiaia_i,最坏情况下求得到x的最小权值 n<=2000n<=2000n Solution: f[i][j]f[i ...

  3. 【QBXT】学习笔记——Day3/4图论+dp

    继续上传一波笔记吧. Day3 1.16AM 今天讲图论,以习题为主. 开篇水题: 给一幅图,若删去一个点后变成一棵树,则这个点合法.问哪些点合法. 思路根据树的性质:这个点不是割点,m-这个点的度数 ...

  4. 强化学习笔记5:learningplanning, explorationexploitation

    1 learning & planning Learning 和 Planning 是序列决策的两个基本问题. 在强化学习中,环境初始时是未知的,agent 不知道环境如何工作,agent 通 ...

  5. 第一章 强化学习介绍

    Reinforement Learning Reinforcement Learning 强化学习讨论的问题是一个 智能体(agent) 怎么在一个复杂不确定的环境(environment)里面去极大 ...

  6. Java面试一百道题目(第一题)-什么是面向对象,谈谈你对面向对象的理解

    Java面试一百道题目(第一题) 1,什么是面向对象,谈谈你对面向对象的理解. 思路:用面向过程和面向对象做对比来突出什么是面向对象. 答:高级语言分为,面向对象语言和面向过程语言,面向过程语言,距离 ...

  7. python导入word转换的html,python如何转换word格式、读取word内容、转成html

    # python如何转换word格式.读取word内容.转成html? import docx from win32com import client as wc # 首先将doc转换成docx wo ...

  8. Reinforement Learning-chapter1

    Reinforement Learning Reinforcement Learning [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sG1oATCa-1603206 ...

  9. Altium Designer AD绘制放置中间挖空无覆铜绿油的mark点

    最近因为项目的需要要用到开钢网,所以就查了查有关ad软件上的钢网教程.但是发现大部分教程只是通过修改焊盘,而没有办法实现焊盘周围挖空去除绿油.所以和大家分享记录一下这个方法. 第一步 在需要放置mar ...

最新文章

  1. php 下划线转大写开头,使用PHP把下划线分隔命名的字符串 转换成驼峰式命名方式 , 把下划线后面的第一个字母变成大写...
  2. Adobe Dreamweaver CS3中文版
  3. openssl 证书生成手册
  4. servlrt程序的入口点是_刚刚,微信偷偷更新,小程序又放大招了!
  5. 大数据 智能交通调度_大数据技术在智能交通中的应用
  6. SAP 电商云 Spartacus UI B2B checkout 点击 Continue 不能跳转到下一页面
  7. 小程序在wxml页面中取整
  8. 知识图谱发展的三个时期以及事理图谱概念辨析
  9. java 展现层框架_spring快速入门例子教程:06展现层
  10. Juniper防火墙备份与恢复处理方法
  11. 命令窗口ping oracle,Oracle中tnsping命令解析
  12. 1.java数组教程及示例知乎
  13. RENIX软件OSPF和BFD、ISIS和BFD联动测试——网络测试仪实操
  14. C++坦克大战源代码
  15. android国际化多语言对照
  16. Java多线程系列--“JUC集合”08之 LinkedBlockingQueue
  17. 如何在Ubuntu MATE 18.04中安装GNOME 3?
  18. 判断时间复杂度和空间复杂度
  19. 四川理工计算机专业好不好,急!!!!四川理工 、 宜宾学院 、 内江师范学院 哪个学校计算机专业好点?...
  20. 【FCN】Fully Convolutional Networks for Semantic Segmentation学习

热门文章

  1. python判断是不是字母_python判断字符是否为字母和数字
  2. 模拟测试电脑性能软件,对比哪个模拟器好 六款电脑手游模拟器安兔兔性能测试跑分...
  3. Acala与全球知名跨链资产流动平台Ren达成合作
  4. laravel 使用SSH 隧道连接到远程数据库
  5. Python ❀ 函数
  6. 日常用语--征求意见
  7. 服务器不显示NPC名字是什么情况,走进科学:一些不明显的服务器名字的由来
  8. 安装pandas成功但import不成功的解决办法
  9. 这可能是前端开发中能遇到最全的cookie问题了
  10. 恒生电子实习记录-2