【单调队列优化DP】LNSYOJ#106. 猴子

这是一道思路比较简单但是调试极其毒瘤的一道题目!

题目描述

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

 

输入格式

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

 

输出格式

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

样例一

input

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

output

20

限制与约定

对于30%的数据,1M<N1001≤M<N≤100

对于50%的数据,1M<N20001≤M<N≤2000

对于100%的数据,1M<N5000,ai10000,bi10000D100001≤M<N≤5000,ai≤10000,bi≤10000,D≤10000

时间限制1s1s

空间限制256MB

首先是状态转移方程dp[k][i]表示到第i棵数已经跳了k步的最多香蕉数

那么转移就是dp[k][i]=max(dp[k-1][q[head]]+val[i],dp[k][i]);

然后呢就是毒瘤的单调队列时间

就是这种数据结构,把它弄成单调的,head弹出,tail插入;

在数组里是把整个队列倒过来放进去的

因为是单调队列

所以插入时候tail--找到要插的位置,然后再++tail位置插进去

弹出时候head++,就弹出了

也就是说在数组里head在左,tail在右,可以脑补这个队列就躺在数组里

一定要注意head要<=tail,要不可能会死循环(网上有个代码就被我hack了)

这道题有一些注意的地方;

有几组数据比较毒瘤,有可能有两个树之间距离很大,导致后面的树全都去不了(见16行特判,被卡掉了30分),这时候需要特殊处理(我直接输出,会跑的很快2333)

上代码!

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 using namespace std;
 6 int n,d,m,head=1,tail=1,ans=-1;
 7 int val[5111],s[5111],dp[5111][5111],q[5111];
 8 int main()
 9 {
10     scanf("%d%d%d",&n,&d,&m);
11     for(int i=1;i<=n;i++)scanf("%d%d",&val[i],&s[i]);
12     dp[0][1]=val[1];
13     for(int k=1;k<=m;k++)
14     {
15         head=tail=1;
16         if(s[k+1]-s[k]>d)
17         {
18             for(int i=1;i<=k;i++)
19                 ans=max(ans,dp[k-1][i]);
20             printf("%d
",ans);
21             return 0;
22         }
23         q[tail]=k;
24         for(int i=k+1;i<=n;i++)
25         {            
26             while(head<=tail && s[i]-s[q[head]]>d)
27                 head++;
28             dp[k][i]=max(dp[k-1][q[head]]+val[i],dp[k][i]);
29             while(head<=tail && dp[k-1][q[tail]]<dp[k-1][i])
30                 tail--;    
31             q[++tail]=i;
32         }
33     }
34     for(int i=1;i<=n;i++)ans=max(ans,dp[m][i]);
35     printf("%d
",ans);
36     return 0;
37 }
原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10123576.html