线段树和单调队列优化DP---POJ2373解题报告

在长为L(<=1000000)的草地(可看成线段)上装喷水头,喷射是以这个喷水头为中心,喷水头的喷洒半径是可调节的,

调节范围为[a,b]。要求草地的每个点被且只被一个喷水头覆盖,并且有些连续区间必须被某一个喷水头覆盖,

而不能由多个喷头分段完全覆盖,求喷水头的最小数目。

很容易想到,这可以用dp解决,定义dp[i]为覆盖[0,i]区间所需的的最小喷头数,

则dp[0]=0,dp[i]=min{dp[i-2*b]....dp[i-2*a]};因为喷头是向两边喷洒的,所以一个喷头覆盖的区间长度一定是偶数,

又由于题目要求喷头不能喷洒到[0,L]以外的区域,所以0开始的长度为奇数的子区间[0,L’]是不能被完全覆盖的。

还有一个问题是,某些连续区间必须被某一个喷水头覆盖这个限制该如何解决。我们可以这样想,

如果[s,e]这个区间只能被一个喷头覆盖,则[0,M](s<M<e)这一段子区间将不允许被完全覆盖,

因为如果[0,M]被完全覆盖会导致[s,e]区间被分割,所以我们可以对所以的[s,e]做上标记,

一种比较方便编码的方法是直接在dp这个数组上用一个特殊的值标记。我的做法是这样的:

dp[0]=0;
for(int i=1; i<=l; i++) dp[i]=inf;
for(int i=0; i<n; i++) {
        int s, e;  
        scanf("%d%d", &s, &e);
        for(int j=s+1; j<e; j++) dp[j] = inf+1;//用inf+1表示不允许覆盖
}

完整代码:

#include<cstdio>
#include<cstring>
#define L 1001000

int a,b,n,l,inf,dp[L];

int dpro(void)
{
     if(b<1) return -1;
     dp[0]=0;
                     
     for(int i=2; i<=l; i+&
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值