POJ 2373 Dividing the Path(DP + 单调队列)
描述
为了使安装更容易,每个喷头必须安装在山脊上(我们可以认为这是一条长度为L(1<=L<=1,000,000)的一维数列;L是偶数)。
每个洒水器沿山脊向两个方向地面排水一段距离。每个喷雾半径是A.B范围内的整数(1<=A<=B<=1000)。农夫约翰需要给整个山脊浇水,用一个喷头覆盖整个山脊上的每一个位置。此外,FJ不会在任何一个方向超过山脊的末端。
每头农场主约翰的N(1<=N<=1000)奶牛都有她特别喜欢的一系列三叶草(这些范围可能重叠)。范围由闭区间(S,E)定义。母牛的每一个选择范围都必须用一个喷头浇水,这种喷头可能会也可能不会在给定的范围内喷水。
找出最小数量的喷头需要浇水整个山脊没有重叠。
输入
*第2行:两个空格分隔的整数:A和B
* Lines 3..N+2: Each line contains two integers, S and E (0 <= S < E <= L) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge and so are in the range 0..L.
输出量
样本输入
- 2 8
- 1 2
- 6 7
- 3 6
样本输出
- 3
暗示
两头母牛沿着一条8长的山脊。喷头在1.2(即1或2)范围内有整数的喷雾半径。一只母牛喜欢3-6的范围,另一只喜欢6-7的范围。
产出详情:
需要三个喷头:一个喷淋距离为1,一个喷淋距离为4,喷雾距离为2,另一个喷淋距离为7,喷雾距离为1。第二个洒水器像第二头牛(3-6)一样,将整个范围内的三叶草全部浇水。最后的洒水所有的范围内的三叶草喜欢的第一头牛(6-7)。下面是一个图表:
- |-----c2----|-c1| cows' preferred ranges
|---1---|-------2-------|---3---| sprinklers
+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8
喷头在2和6处不被认为是重叠的。
从线段的起点向终点安装喷水头,令f(X)表示:所安装喷水头的喷洒范围 恰好覆盖直线上的区间[0 X]时,最少需要多少个喷水头
显然,X应满足下列条件:
X为偶数
X所在位置不会出现奶牛,即X不属于任何一个(S,E)
X>=2A
当X<=2B时,存在Y属于[X-2B X-2A]且Y满足上述三个条件,使得 f(X)=f(Y)+1
对每个X求f(X),都要遍历区间 [X-2B, X -2A]去寻找其中最小的 f(Y),则时间复杂度为:L * B = 1000000 * 1000,太慢,快速找到[X-2B X-2A]中使得f(Y)最小的元素是问题求解速度的关键 。
!!!
可以使用优先队列priority_queue! (multiset也可以,比 priority_queue慢一点)!
求F(X)时,若坐标属于[X-2B, X-2A]的二元组(i,F(i))都保存在 一个priority_queue中,并根据F(i)值排序,则队头的元素就能 确保是F(i)值最小的。在求X点的F(x)时,必须确保队列中包含所有属于 [X-2B,X-2A]的点。 而且,不允许出现坐标大于X-2A的点,因为这样的点对求F(X)无用,如果这样的点出现在队头,因其对求后续点的F值有用,故不能抛弃之,于是算法就无法继续了。
队列中可以出现坐标小于 X-2B 的点。这样的点若出现在队头,则直接将其抛弃。
求出X点的F值后,将(X-2A+2, F(X-2A+2))放入队列,为求F(X+2)作准备
代码:
- #include<iostream>
- #include<queue>
- using namespace std;
- const int INF = 0x3f3f3f;
- const int MAXL = ;
- int cowThere[MAXL];//cowThere[i]为1表示点i有奶
- int dp[MAXL];// dp[L]就是答案
- struct Fx {
- int x;
- int f;
- bool operator<(const Fx & a) const { return f > a.f; }
- Fx(int xx=,int ff=):x(xx),f(ff) { }
- };// 在优先队列里,f值越小的越优先
- priority_queue<Fx> qFx;
- int main() {
- int N, L, A, B;
- cin >> N >> L;
- cin>> A >> B;//A,B的定义变为覆盖的直径
- A <<= ; B <<= ;
- for(int i = ; i < N; i++) {
- int s, e;
- cin >> s >> e;
- cowThere[s+]++;//从s+1进入一个奶牛区
- cowThere[e]--;//从e起退出一个奶牛区
- }
- int inCows = ; //表示当前点位于多少头奶牛的活动范围之内
- for(int i = ; i <= L; i++) {//算出每个点是否有奶牛
- dp[i] = INF;
- inCows += cowThere[i];
- cowThere[i] = inCows > ;
- }
- for(int i = A; i <= B; i += ) {//初始化队列
- if(!cowThere[i]) {
- dp[i] = ;
- if(i <= B + - A) {//在求dp[i]的时候,要确保队列里的点x,x <= i - A
- qFx.push(Fx(i, ));
- }
- }
- }
- for(int i = B + ; i <= L; i += ) {
- if(!cowThere[i]) {
- Fx fx;
- while(!qFx.empty()) {
- fx = qFx.top();
- if(fx.x < i - B) qFx.pop();
- else break;
- }
- if(!qFx.empty()) {
- dp[i] = fx.f + ;
- }
- }
- //队列中增加一个可达下个点的点,为下一个dp(i+2)做准备
- if(dp[i + - A] != INF) qFx.push(Fx(i + - A, dp[i + - A]));
- }
- if(dp[L] == INF) cout << - << endl;
- else cout << dp[L] << endl;
- return ;
- }
POJ 2373 Dividing the Path(DP + 单调队列)的更多相关文章
- POJ 2373 Dividing the Path (单调队列优化DP)题解
思路: 设dp[i]为覆盖i所用的最小数量,那么dp[i] = min(dp[k] + 1),其中i - 2b <= k <= i -2a,所以可以手动开一个单调递增的队列,队首元素就是k ...
- 【POJ】2373 Dividing the Path(单调队列优化dp)
题目 传送门:QWQ 分析 听说是水题,但还是没想出来. $ dp[i] $为$ [1,i] $的需要的喷头数量. 那么$ dp[i]=min(dp[j])+1 $其中$ j<i $ 这是个$ ...
- poj 2373 Dividing the Path
Dividing the Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2858 Accepted: 1064 ...
- POJ - 3162 Walking Race 树形dp 单调队列
POJ - 3162Walking Race 题目大意:有n个训练点,第i天就选择第i个训练点为起点跑到最远距离的点,然后连续的几天里如果最远距离的最大值和最小值的差距不超过m就可以作为观测区间,问这 ...
- [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)
DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...
- DP+单调队列 codevs 1748 瑰丽华尔兹(还不是很懂具体的代码实现)
codevs 1748 瑰丽华尔兹 2005年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Descripti ...
- 习题:烽火传递(DP+单调队列)
烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台 ...
- (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列
Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...
- 3622 假期(DP+单调队列优化)
3622 假期 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description 经过几个月辛勤的工作,FJ决定让奶牛放假.假期可以在1-N天内任意选择 ...
随机推荐
- js全选 反选
// 全选 反选 allChoose: function (o) { var obj = $.extend(true, { id: "#id", name: "name& ...
- pandas计数 value_counts()
来自:曹骥 在pandas里面常用value_counts确认数据出现的频率. 1. Series 情况下: pandas 的 value_counts() 函数可以对Series里面的每个值进行计数 ...
- 百万并发中间件系统的内核设计看Java并发性能优化
“ 这篇文章,给大家聊聊一个百万级并发的中间件系统的内核代码里的锁性能优化. 很多同学都对Java并发编程很感兴趣,学习了很多相关的技术和知识.比如volatile.Atomic.synchroniz ...
- leecode第一百四十二题(环形链表II)
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...
- 算法笔记--最大流和最小割 && 最小费用最大流 && 上下界网络流
最大流: 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 最小割: 割是网 ...
- Day2-异步IO+Scrapy爬虫
一.异步IO http://www.cnblogs.com/wupeiqi/articles/6229292.html 这篇文章写的不错,展示了多种高并发的方式,从同步执行→多线程→多进程→async ...
- 日常英语---十、MapleStory/Monsters/Level 191-201(Sad Erda:向你发射炮弹进行攻击)
日常英语---十.MapleStory/Monsters/Level 191-201(Sad Erda:向你发射炮弹进行攻击) 一.总结 一句话总结:一种悲伤的精神,形成于奥术之河,一个黑法师能够融合 ...
- 雷林鹏分享:jQuery EasyUI 树形菜单 - 树形网格惰性加载节点
jQuery EasyUI 树形菜单 - 树形网格惰性加载节点 有时我们已经得到充分的分层树形网格(TreeGrid)的数据. 我们还想让树形网格(TreeGrid)按层次惰性加载节点. 首先,只加载 ...
- 1.4 Crack小实验
0_day 第一章 基础知识 1.4 Crack小实验 <0day_2th>王清 著 电子书 下载链接:https://pan.baidu.com/s/11TgibQSC3-kYwCInm ...
- Spring Cloud之配置中心搭建
一.配置中心服务端搭建 1)引入相关Maven坐标 <dependency> <groupId>org.springframework.cloud</groupId> ...