猴子

来源:互联网 发布:2016淘宝小号批量注册 编辑:程序博客网 时间:2024/05/17 09:19

Description

一个猴子找到了很多香蕉树,这些香蕉树都种在同一直线上,而猴子则在这排香蕉树的第一棵树上。这个猴子当然想吃尽量多的香蕉,但它又不想在地上走,而只想从一棵树跳到另一棵树上。同时猴子的体力也有限,它不能一次跳得太远或跳的次数太多。每当他跳到一棵树上,它就会把那棵树上的香蕉都吃了。那么它最多能吃多少个香蕉呢?

Input

输入第一行为三个整数,分别是香蕉树的棵数N,猴子每次跳跃的最大距离D,最多跳跃次数M。  下面N行每行包含两个整数,ai,bi,分别表示每棵香蕉树上的香蕉数,以及这棵树到猴子所在树的距离。输入保证这些树按照从近到远排列,并且没有两棵树在同一位置。b0总是为0。

Output

输出只有一行,包含一个整数,为猴子最多能吃到的香蕉数。

Sample Input

5 5 26 08 34 56 79 10

Sample Output

20

HINT

100%的数据有M<N<=2000,bi<=10000

Key To Problem

依旧是dp+单调队列优化。f[i][j]表示的状态为在跳i次时跳到第j棵树最大可以获得的香蕉数量。f[i][j]=max{f[i-1][k]}+a[j](b[j]-b[k]<=d);单调队列维护单调递减区间。

code

#include<cstdio>#include<algorithm>#define N 2010using namespace std;int n,d,m;int a[N];int b[N];int f[N][N];int que[N];int main(){    scanf("%d%d%d",&n,&d,&m);    for(int i=1;i<=n;i++)        scanf("%d%d",&a[i],&b[i]);    f[0][1]=a[1];    for(int i=1;i<=m;i++)    {        int head=1,tail=0;        for(int j=i+1;j<=n;j++)        {            while(tail>=head&&f[i-1][j-1]>=f[i-1][que[tail]])                tail--;            que[++tail]=j-1;            while(b[j]-b[que[head]]>d)                head++;            f[i][j]=f[i-1][que[head]]+a[j];        }    }    int ans=0;    for(int i=1;i<=n;i++)        ans=max(ans,f[m][i]);    printf("%d\n",ans);    return 0;}
1 1
原创粉丝点击