BZOJ1915: [Usaco2010 Open]奶牛的跳格子游戏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1915: [Usaco2010 Open]奶牛的跳格子游戏相关的知识,希望对你有一定的参考价值。

权限题,没有传送门。

这很显然是一道DP题,刚看完题目可能会比较懵逼。这道题如果不要求回去,那么就是一道很裸的DP题。但是本题要求回去而且回去的格子的前一个格必须是之前经过的。

先不考虑回去的路程,对于一段长度在$K$之内的区间,其中的所有值为正数的点都是可以到达的。所以先搞个前缀和:

$sum_i= \\sum _{j=1}^i a_j \\times [a_j>0]$

这个搞完后如果不算回来的,可以得到以下转移方程:

$f[i]=max \\{ f[j]+sum[i-1]-sum[j] \\}$

其实到这一步,带上回去的状态转移方程也很显然了。

$f[i]=max \\{f[j]+sum[i-2]-sum[j]+a[i]+a[i-1] \\}$

表示第$i$个点为去时经过的点且会返回的前一个点,$sum[]$和$f[]$均存在单调性,所以可以用单调队列优化决策单调性,使得总体复杂度降为$O(N)$。

但是$f[i]_{max}$并不是最后的答案,因为对于任意一个点$i$,$[i+1,i-1+K]$都是可以到达的,所以要把这一段对答案的贡献也累加上。

 

在具体实现时,注意单调队列在DP前应进队0和1,因为第0个点不是必须停留的点。

技术分享
 1 //BZOJ 1915
 2 //by Cydiater
 3 //2016.10.6
 4 #include <iostream>
 5 #include <cstring>
 6 #include <string>
 7 #include <algorithm>
 8 #include <queue>
 9 #include <cstdio>
10 #include <cmath>
11 #include <ctime>
12 #include <map>
13 #include <iomanip>
14 #include <cstdlib>
15 using namespace std;
16 #define ll long long
17 #define up(i,j,n)        for(int i=j;i<=n;i++)
18 #define down(i,j,n)        for(int i=j;i>=n;i--)
19 const int MAXN=3e6+5;
20 const int oo=0x3f3f3f3f;
21 inline ll read(){
22     char ch=getchar();ll x=0,f=1;
23     while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
24     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
25     return x*f;
26 }
27 ll N,K,sum[MAXN],a[MAXN],q[MAXN],head,tail,f[MAXN],ans=0;
28 namespace solution{
29     void init(){
30         memset(sum,0,sizeof(sum));
31         N=read();K=read();
32         up(i,1,N)a[i]=read();
33         up(i,1,N)sum[i]=sum[i-1]+(a[i]>0?a[i]:0);
34     }
35     void DP(){
36         head=1;tail=0;q[++tail]=0;q[++tail]=1;
37         up(i,2,N){
38             while(head<tail&&i-q[head]>K)head++;
39             f[i]=f[q[head]]+sum[i-2]-sum[q[head]]+a[i]+a[i-1];
40             while(head<tail&&f[i]-f[q[tail]]>sum[i]-sum[q[tail]])tail--;
41             q[++tail]=i;
42         }
43         up(i,1,N)ans=max(ans,f[i]+((i-1+K<=N)?(sum[i-1+K]-sum[i]):(sum[N]-sum[i])));
44     }
45     void output(){
46         cout<<ans<<endl;
47     }
48 }
49 int main(){
50     //freopen("input.in","r",stdin);
51     using namespace solution;
52     init();
53     DP();
54     output();
55     return 0;
56 }
View Code

 

以上是关于BZOJ1915: [Usaco2010 Open]奶牛的跳格子游戏的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形

BZOJ1916: [Usaco2010 Open]冲浪

BZOJ1914: [Usaco2010 OPen]Triangle Counting 数三角形

bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形——极角排序

bzoj4576Usaco2016 Open262144

[BZOJ3535][Usaco2014 Open]Fair Photography