NKOJ P3662 [usaco 2004 dec gold] 划区灌溉【单调队列优化DP】

首先对于奶牛要求的 [ S i , E i ] ,由于不能被不同的喷灌器喷灌,所以我们在处理的时候考虑用开区间 ( S i , E i )

D P [ i ] 表示当覆盖区间为 [ 1 , i ] 时用的最少的喷灌器的数量,

D P [ i ] = m i n ( D P [ j ] ) + 1 , A i j 2 B

由于转移中的 D P [ i ] D P [ j ] 始终满足单调性,用单调队列记录值与编号优化即刻。

额外记录是否有解。

#include <bits/stdc++.h>
using namespace std;
const int Max=1e6+5;
const int Inf=1e9;
struct Node{
    int Id,V;
};deque<Node>DQ;
int DP[Max],Flag[Max];
int N,M,A,B,Mark=1,X[Max],Y[Max];
int main(){
    int I,J,K;
    scanf("%d%d%d%d",&N,&M,&A,&B);
    for(I=1;I<=N;I++){
        scanf("%d%d",&X[I],&Y[I]);
        if(2*B<Y[I]-X[I]){
            Mark=0;
        }
    }Flag[0]=1;
    if(Mark==1){
        for(I=1;I<=M;I++){
            DP[I]=Inf,Flag[I]=1;
        }
        for(I=1;I<=N;I++){
            for(J=X[I]+1;J<=Y[I]-1;J++){
                Flag[J]=0;
            }
        }
        DQ.push_back(Node{0,0});
        for(I=2*A;I<=M;I+=2){
            int Pos=I-2*A;
            if(Flag[Pos]==1){
                while(DQ.size()!=0&&DQ.back().V>=DP[Pos]){
                    DQ.pop_back();
                }
                DQ.push_back(Node{Pos,DP[Pos]});
            }Pos=I-2*B;
            while(DQ.size()!=0&&DQ.front().Id<Pos){
                DQ.pop_front();
            }
            if(Flag[I]==1&&DQ.size()!=0){
                DP[I]=DQ.front().V+1;
            }
        }
    }
    if(Mark==0||Inf<=DP[M]){
        puts("-1");
    } else {
        printf("%d",DP[M]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81501250
今日推荐