划区灌溉
Time Limit:10000MS Memory Limit:65536K
Total Submit:16 Accepted:10
Case Time Limit:1000MS
Description
约翰的奶牛们发现山脊上的草特别美味.为了维持草的生长,约翰打算安装若干喷灌器.为简化问题,山脊可以看成一维的数轴,长为L(1≤L≤10^6),而且L-定是一个偶数.每个喷灌器可以双向喷灌,并有确定的射程,该射程不短于A,不长于B,A,B(1≤A≤B≤10^3)都是给出的正整数.它所在位置的两边射程内,都属它的灌溉区域.注意,一个喷灌器往左右两边喷射的距离是一样的,比如往左喷的距离是x,那么往右也是x,(A<=x<=B)。
现要求山脊的每一个区域都被灌溉到,喷灌器不能将水喷到山脊以外的区域,而且喷灌器的灌溉区域不允许重叠, 约翰有N(1≤N≤10^3)只奶牛,每一只都有特别喜爱的草区,第i奶牛喜爱的草区是[Si,Ei],不同奶牛的草区可以重叠(Ei-Si<=2*B).现要求,每只奶牛的草区仅被一个喷灌器灌溉. 寻找最少需要的喷灌器数目.
Input
第一行,两个整数N和L
第二行,两个整数A和B
接下来N行,每行两个整数S和E(0 <= S < E <= L),表示每头奶牛喜欢的草区的起止位置
Output
一行,一个整数,表示最少需要的喷灌器的数量,若无解,输出-1
Sample Input
样例输入1:
2 8
1 2
6 7
3 6
样例输入2:
4 202
10 12
21 27
32 39
103 121
163 180
Sample Output
样例输出1:
3
样例输出2:
10
Hint
Source
usaco 2004 dec gold
<pre name="code" class="cpp">#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<algorithm> #include<cstring> #include<deque> #define inf 1e9 using namespace std; struct node{ int l,r;//记录每头牛喜欢草地的左界和右界 (或者队列里的元素) node(){} node(int a,int b){l=a;r=b;} }; bool ok[1000005];//ok记录每一个草区是否是奶牛所喜欢的 int f[1000005];//f[i]表示从0--i号草区所需的最少喷灌器 node cow[10005]; bool flag=true;//记录是否无解 deque<node>q; int main(){ int n,l,a,b,i,j,k,temp; scanf("%d%d%d%d",&n,&l,&a,&b); for(i=1;i<=n;i++){ scanf("%d%d",&cow[i].l,&cow[i].r);//init if(cow[i].r-cow[i].l>2*b){ flag=false; } } ok[0]=true; if(flag){ for(i=1;i<=l;i++){ f[i]=inf;ok[i]=true; } for(i=1;i<=n;i++){ for(j=cow[i].l+1;j<cow[i].r;j++){//取用开区间 ok[j]=false; }} q.push_back(node(0,0)); for(i=2*a;i<=l;i+=2){ temp=i-2*a;//第i号草区当然应该讨论i-2*a到i-2*b if(ok[temp]){ while(q.size()&&q.back().r>=f[temp])q.pop_back(); q.push_back(node(temp,f[temp])); } temp=i-2*b; while(q.size()&&q.front().l<temp)q.pop_front(); if(ok[i]&&q.size())f[i]=q.front().r+1;//只有在第i号草区不属于每一头牛的喜欢区域才可以dp,否则搞成inf } } if(flag==false||f[l]>=inf)cout<<"-1"; else cout<<f[l]; }