JZOJ-senior-1773. 【NOIP动态规划专题】猴子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HuangXinyue1017/article/details/83473732

Time Limits: 1000 ms Memory Limits: 65536 KB

Description

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

Input

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

Output

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

Sample Input

5 5 2 6 0 8 3 4 5 6 7 9 10

Sample Output

20

Data Constraint

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

Solution

  • 显然DP,设 f i , j f_{i,j} 表示跳了 i i 次,到达第 j j 棵树上的能吃到的最多的香蕉数
  • 那么 f i , j = m a x ( f i 1 , k + a [ j ] f_{i,j}=max({f_{i-1,k}+a[j]} )(b[j]-b[k]<=D)
  • 乍一看, O ( n 3 ) O(n^3) ,于是考虑优化DP
  • 容易发现,对于跳同样步数的决策 j , k ( j &lt; k ) j,k(j&lt;k)
  • 要是决策 k k 不仅能吃到更多的香蕉,而且能到达更远的位置,那么决策 j j 就没有了意义
  • 于是我们用单调队列优化即可

Code

#include<algorithm>
#include<cstdio>

#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)

using namespace std;

const int N=2010;
int n,m,k,ans;
int a[N],d[N],q[N],f[N][N];

int main()
{
	freopen("monkey.in","r",stdin);
	freopen("monkey.out","w",stdout);
	scanf("%d%d%d",&n,&k,&m);
	fo(i,1,n) scanf("%d%d",&a[i],&d[i]);
	f[0][1]=a[1];
	fo(i,1,m)
	{
		int l=1,r=0;
		fo(j,i+1,n)
		{
			while(r>=l&&f[i-1][j-1]>=f[i-1][q[r]]) --r;
			q[++r]=j-1;
			while(d[j]-d[q[l]]>k) ++l;
			f[i][j]=f[i-1][q[l]]+a[j];
			ans=max(ans,f[i][j]);
		}
	}
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/HuangXinyue1017/article/details/83473732
今日推荐