poj2373灌溉草场



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 
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 
Each of Farmer John's N (1 
Find the minimum number of sprinklers required to water the entire ridge without overlap.

输入描述

* 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 an

输出描述

* Line 1: The minimum number of sprinklers required.  If it is not possible to design a sprinkler head configuration for Farmer John, output -1.


输入:

2 8

1 2

6 7

3 6


输出:

3


超时代码:L的范围可达一百万,所以在极端的数据下,程序超时了

#include<cstdio>
#include<cstring>
const int L=1e6+10;
int a,b,n,l,inf,dp[L];
int dpro(void)
{
        if(b<1)
                return -1;
        dp[0]=0;//定义dp[i]为覆盖[0,i]区间所需的的最小喷头数,
        for(int i=2; i<=l; i+=2)//l必须是偶数
        {
                if (dp[i]<=inf)
                {
                        int min = inf;
                        for(int j=a; j<=b; j++)
                        {
                                int idx = i-2*j;
                                if(idx<0)//最大2b的范围
                                        break;
                                if ( min>dp[idx] )//满足区间
                                        min=dp[idx];
                        }
                        dp[i]=min+1;
                        //printf("%d ",dp[i]);
                }
        }
        if(dp[l]>=inf)
                return -1;
        else
                return dp[l];
}
int main()
{
        while (scanf("%d%d", &n, &l)!=EOF)
        {
                scanf("%d%d", &a, &b);
                inf = (l/a)+9;
                for(int i=0; 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;
                }
                /*for(int i=0;i<=l;i++)
                printf("%d ",dp[i]);
                printf("\n");*/
                if(l&1==1)
                        printf("-1\n");//l必须是偶数
                else
                        printf("%d\n", dpro());
        }
        return 0;
}


动态规划+线段树优化


#include<cstdio>
#include<cstring>
#define L 1001000
int a,b,n,l,inf,dp[L];
int tree[4*L];
void updata(int *p, int rt, int l, int r,int pos, int k)
{
        if (l==r)
        {
                p[rt]=k;
                return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)
                updata(p,rt<<1, l, mid, pos, k);
        else
                updata(p, rt<<1|1, mid+1, r, pos, k);
        int lv=p[rt<<1];
        int rv=p[rt<<1|1];
        p[rt]=lv<rv?lv:rv;
}


int query(int *p,int rt, int l,int r, int s, int e)
{
        if(l==s && e==r)
                return p[rt];
        int mid = (l+r)>>1;
        if(e<=mid)
                return query(p, rt<<1, l, mid, s, e);
        if(s>mid)
                return query(p, rt<<1|1, mid+1, r, s, e);
        int lv=query(p,rt<<1, l, mid, s,mid);
        int rv=query(p,rt<<1|1, mid+1, r, mid+1, e);
        return lv<rv?lv:rv;
}


int dpro(void)
{
        if(b<1)
                return -1;
        dp[0]=0;
        for(int j=0; j<4*L; j++)
                tree[j]=L*2;
        for(int j=a; j<=b; j++)
        {
                if(dp[2*j]<=inf)
                        dp[0+2*j] = dp[0]+1;
                updata(tree,1, 1, l ,j,dp[2*j]);
        }
        for(int i=2*b+2; i<=l; i+=2)
        {
                int min;
                int pos = (i>>1);
                min = query(tree, 1, 1, l, pos-b, pos-a);
                if (dp[i]<=inf)
                {        //if(dp[i]>min+1)
                        dp[i]=min+1;
                        updata(tree,1,1,l,pos,dp[i]);
                        /*for(int j=a; j<=b; j++) {
                         int idx = i-2*j;
                         if(idx<0) break;
                         if ( dp[i]>dp[idx]+1 ) dp[i]=dp[idx]+1;
                        }*/
                }
        }
        if(dp[l]>=inf)
                return -1;
        else
                return dp[l];
}


int main()
{
        while (scanf("%d%d", &n, &l)!=EOF)
        {
                scanf("%d%d", &a, &b);
                inf = (l/a)+9;
                for(int i=0; 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;
                }
                if(l&1==1)
                        printf("-1\n");
                printf("%d\n", dpro());
        }
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值