题干:
Farmer John's cows have discovered that the clover growing along the ridge of the hill in his field is particularly good. To keep the clover watered, Farmer John is installing water sprinklers along the ridge of the hill.
To make installation easier, each sprinkler head must be installed along the ridge of the hill (which we can think of as a one-dimensional number line of length L (1 <= L <= 1,000,000); L is even).
Each sprinkler waters the ground along the ridge for some distance in both directions. Each spray radius is an integer in the range A..B (1 <= A <= B <= 1000). Farmer John needs to water the entire ridge in a manner that covers each location on the ridge by exactly one sprinkler head. Furthermore, FJ will not water past the end of the ridge in either direction.
Each of Farmer John's N (1 <= N <= 1000) cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval (S,E). Each of the cow's preferred ranges must be watered by a single sprinkler, which might or might not spray beyond the given range.
Find the minimum number of sprinklers required to water the entire ridge without overlap.
Input
* Line 1: Two space-separated integers: N and L
* Line 2: Two space-separated integers: A and 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.
Output
* Line 1: The minimum number of sprinklers required. If it is not possible to design a sprinkler head configuration for Farmer John, output -1.
Sample Input
2 8
1 2
6 7
3 6
Sample Output
3
Hint
INPUT DETAILS:
Two cows along a ridge of length 8. Sprinkler heads are available in integer spray radii in the range 1..2 (i.e., 1 or 2). One cow likes the range 3-6, and the other likes the range 6-7.
OUTPUT DETAILS:
Three sprinklers are required: one at 1 with spray distance 1, and one at 4 with spray distance 2, and one at 7 with spray distance 1. The second sprinkler waters all the clover of the range like by the second cow (3-6). The last sprinkler waters all the clover of the range liked by the first cow (6-7). Here's a diagram:
|-----c2----|-c1| cows' preferred ranges
|---1---|-------2-------|---3---| sprinklers
+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8
The sprinklers are not considered to be overlapping at 2 and 6.
题目大意:
(这个示意图是真误导人啊,还是来说说更详细的题意吧)
在长为L(<=1000000)的草地(可看成一维的线段)上装喷水头,喷射是以这个喷水头为中心,喷水头的喷洒半径是可调节的(但是这题的喷水头只用考虑一个维度的,即不需要看成是个二维平面的一个圆),调节范围为[A,B](注意这里需要理解成,安装完毕的喷水头,喷洒半径就是个定值了,不能来回改变。换句话说这里可以这么理解,市场中有多种喷水头,喷水半径分别是[A,B]中的整数)。要求草地的每个点被且只被一个喷水头覆盖。接下来给你N头牛,给出每头牛的活动范围,并且要求在这个活动范围内只能有一个喷水头来覆盖,也就是不能被两个喷水头来拼接覆盖(也就是不能由多个喷头分段完全覆盖)。求使用喷水头的最小数目。(还有个要求,喷水头不能喷到0~L之外的区域)
解题报告:
注意到因为有“每个点只能被一个喷水头覆盖”的限制,所以喷水头的半径不是选择的越大越好。
明确了题意之后我们来考虑简化一下题目给的信息和要求。
首先我们要把喷头等价到右端点上,不然没法做。也就是把以“每个喷水头可以喷洒到喷水头为中心的一个双向区域”的这个信息变成“喷水头固定放到整个喷洒区域的右端点,也就是每个喷水头只可以向左喷洒”(这就像是 dp前构造一个贪心的策略一样,相当于根据题目中这一个 “ 与喷头放置具体位置无关,只需要关心喷洒区域 ” 的性质,我们在不改变题目含义的情况下强行加一个条件来方便我们进行处理,这一点技巧很常用)
设dp[i]代表完全覆盖 0~i 这个区域,需要的最少喷水头是多少。首先注意到每一个奶牛的区间只能被一个喷头喷到,而你要进行后面的处理dp[i]如果是合法的,肯定是要由某个合法的dp[j] ( i - 2*B <= j <= i - 2*A ) 转移过来。(显然满足dp的无后效性性质,这一点就不证明了)
那么现在题目中还剩下一个限制条件我们还没有用到,那就是每头牛的活动区域只能用一个喷水头单独覆盖,那么根据我们刚刚的假设:喷头等价到右端点上,所以对于中间的每一个点都是不需要处理直接dp[]=INF的。(当然虽然dp值不需要处理,但是单调队列还是要维护的)(这也可见等价转化这个假设是多么的重要)
还有一点是需要注意的,这题因为要求是所有点都要被覆盖,所以要求合法点一定是偶数点,并且要求题目输入的L一定是偶数,不然肯定是非法的。所以你在遍历的时候遇到奇数点可以直接略过了(但是代码中写了,主要是因为要处理差分数组的原因),之所以可以直接略过其实是因为,这题不论维护的哪一个信息,其实都和奇数位置的点没关系,而唯一起作用的地方就是在牛的活动范围那里,用以判断接下去的偶数点是否dp[]值需要是非法值。(这题中奇数位置上的点的dp值甚至都不需要去管,因为全程没用到)
感受dp的奇妙吧!dp经常可以附带一个附加效果就是可以把非法情况直接给带出来了,比如这题就不需要取特判-1的情况,而是直接去dp数组中取数就可以了。
至于为什么考虑奇数的点就会WA呢?按理来说dp也是可以处理这种非法情况的呀?但是请考虑这样一个问题,你的喷洒头的长度是偶数的(因为乘以2算直径了嘛)如果你那么用的话,那么队列中不止会有偶数距离的值,还会存了奇数距离,而奇数距离是非法的!(因为喷洒的直径肯定是偶数)那么你在单调队列取值的时候就需要用判断的方式来得到需要的解了,而不是刻意直接取数就是答案。(我感觉是因为这个原因,当然也可能是其他原因吧,反正奇数的在这个题中本就是卵用没有呀)
再就是代码细节比较多,比如维护单调性的时候必须要i-A>=0(别忘等号!因为dp[0]本身就是要用到的合法解),但是维护区域的时候就不需要i-A>=0。
至于为什么需要i-A>=0,还是因为题意:喷泉不能喷出去...比如线段的长度是4..而我手上的喷泉能喷的距离是(2~3)...结果是-1...因为不论我喷泉在0-3的范围放哪里...所以按照题意应该输出-1、
还有个问题,为什么这题可以用单调队列呢?因为A和B都是常数,所以维护的窗口肯定是单调的往后移动的,所以可以这样。
AC代码:
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e6 + 5;
const int INF = 0x3f3f3f3f;
int c[MAX];
int n,L,A,B;
deque<int> dq;
int dp[MAX];
int main()
{
cin>>n>>L;
cin>>A>>B;
A*=2,B*=2;
for(int s,e,i = 1; i<=n; i++) {
scanf("%d%d",&s,&e);
s++,e--;
c[s]++;c[e+1]--;
}
dp[0]=0;
for(int i = 1; i<=L; i++) {
c[i] += c[i-1];
if(i & 1) continue;
while(dq.size() && dq.front() < i - B) dq.pop_front();
if(i-A>=0) {
while(dq.size() && dp[dq.back()] > dp[i-A]) dq.pop_back();
dq.push_back(i-A);
}
if(dq.size() && dp[dq.front()] < INF && c[i] == 0) dp[i] = dp[dq.front()]+1;
else dp[i] = INF;
}
if(dp[L] == INF) printf("-1");
else printf("%d",dp[L]);
return 0 ;
}