zoukankan      html  css  js  c++  java
  • POJ2373 Dividing The Path 题解

    题目描述

    约翰的奶牛们发现山脊上的草特别美味。为了维持草的生长,约翰打算安装若干喷灌器。
    为简化问题,山脊可以看成一维的数轴,长为 L (1 <= L <= 1,000,000) ,而且L一定是一个偶数。每个喷灌器可以双向喷灌,并有确定的射程,该射程是一个整数,且不短于A,不长于B , A、B(1 <= A <= B <= 1000)都是给出的正整数。它所在位置的两边射程内,都属它的灌溉区域。
    现要求山脊的每一个区域都被灌溉到,而且喷灌器的灌溉区域不允许重叠。
    约翰有 N (1 <= N <= 1000)只奶牛,每一只都有特别喜爱的草区,第i只奶牛的草区是[Si,Ei],不同奶牛的草区可以重叠。现要求,每只奶牛的草区仅被一个喷灌器灌溉。

    一道单调队列优化DP的练手题,下面讲讲思路:

    首先提到对于每一个Si--Ei,不能被不同的喷灌器喷灌,那么也就是说Si+1--Ei-1都不能成为任何一个喷灌器的右边界,所以我们开一个数组 l[i] 判断 i 能否成为某一个喷灌器的右边界,若可以,l[i]=false,反之,l[i]=true。

    接着,我们考虑状态,定义f[i]表示当覆盖长度为 i 时用的最少的喷灌器的数量,也就是说,i是一个喷灌器的右边界,我们要枚举它的左边界,所以对于每一个合法的i(即l[i]==false),有如下的状态转移方程

    \[f[i]=min(f[j]+1)(A<=(i-j)/2<=B) \]

    很明显,这样做的时间复杂度是O(n*n)的,不可取。

    仔细研究状态转移方程,我们发现f[i]一定是由满足A<=(i-j)/2<=B且f[j]最小的j转移过来的,所以选用单调队列维护这个最小值。当(i-队首元素下标)/2>B时,队首元素出队。另外还要再开一个队列存储元素编号,只有当这个队列队首元素的下标满足(i-队首元素下标)/2>=A时,才可以将这个元素压进单调队列。

    这样就可以优化到O(n)的复杂度了,问题解决。

    代码如下:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    int N,L,A,B,s,e;
    int q[1000001],head=1,tail;
    int p[1000001],h=1,t;
    int f[1000001];//f[i]表示当覆盖长度为i时最少的喷灌器数目 
    bool l[1000001];
    int main()
    {
        scanf("%d%d",&N,&L);
        scanf("%d%d",&A,&B);
        for(register int i=1;i<=N;i+=1)
        {
            scanf("%d%d",&s,&e);
            for(register int j=s+1;j<=e-1;j+=1)l[j]=true;
        }
        memset(f,127,sizeof(f));
        f[0]=0;
        p[++t]=0;
        for(register int i=2;i<=L;i+=2)
        {
            if(l[i]==true)continue;
            while(h<=t&&(i-p[h])/2>=A)
            {
                while(head<=tail&&f[q[tail]]>=f[p[h]])tail--;
                q[++tail]=p[h];
                h++;
            }
            while(head<=tail&&(i-q[head])/2>B)head++;
            if(head<=tail)
            {
                f[i]=f[q[head]]+1;
                p[++t]=i;
            }
        }
        if(f[L]!=2139062143)printf("%d\n",f[L]);
        else printf("-1\n");
        return 0;
    }
    
  • 相关阅读:
    深入 kernel panic 流程【转】
    HDMI驱动热插拔检测方法
    WFE和WFI的区别
    SMP多核启动
    CPUFreq驱动
    DMA与cache一致性的问题
    深度理解select、poll和epoll
    Memory barrier 简介
    thinkphp的删除操作
    HOST文件配置
  • 原文地址:https://www.cnblogs.com/ForwardFuture/p/9022041.html
Copyright © 2011-2022 走看看