标签:str 设计 不可 break 输出 不能 empty ios pac
描述
输入
输出量
样本输入
2 8 1 2 6 7 3 6
样本输出
3
暗示
|-----c2----|-c1| cows‘ preferred ranges
|---1---|-------2-------|---3---| sprinklers
+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8
从线段的起点向终点安装喷水头,令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 = 1000010; 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=0,int ff=0):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 <<= 1; B <<= 1; for(int i = 0; i < N; i++) { int s, e; cin >> s >> e; cowThere[s+1]++;//从s+1进入一个奶牛区 cowThere[e]--;//从e起退出一个奶牛区 } int inCows = 0; //表示当前点位于多少头奶牛的活动范围之内 for(int i = 0; i <= L; i++) {//算出每个点是否有奶牛 dp[i] = INF; inCows += cowThere[i]; cowThere[i] = inCows > 0; } for(int i = A; i <= B; i += 2) {//初始化队列 if(!cowThere[i]) { dp[i] = 1; if(i <= B + 2 - A) {//在求dp[i]的时候,要确保队列里的点x,x <= i - A qFx.push(Fx(i, 1)); } } } for(int i = B + 2; i <= L; i += 2) { 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 + 1; } } //队列中增加一个可达下个点的点,为下一个dp(i+2)做准备 if(dp[i + 2 - A] != INF) qFx.push(Fx(i + 2 - A, dp[i + 2 - A])); } if(dp[L] == INF) cout << -1 << endl; else cout << dp[L] << endl; return 0; }
POJ 2373 Dividing the Path(DP + 单调队列)
标签:str 设计 不可 break 输出 不能 empty ios pac
原文地址:https://www.cnblogs.com/kindleheart/p/9505090.html