poj2373灌溉草场

来源:互联网 发布:手机修改图片软件 编辑:程序博客网 时间:2024/05/16 00:26



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;
}