【USACO 2011 Open】修剪草坪(DP)

题目描述

在一年前赢得了小镇的最佳草坪比赛后,FJ 变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,FJ 希望能够再次夺冠。
然而,FJ 的草坪非常脏乱,因此,FJ 只能够让他的奶牛来完成这项工作。FJ 有 N 只排成一排的奶牛,编号为 1...N。每只奶牛的效率是不同的,奶牛 i 的效率为 E_i。
靠近的奶牛们很熟悉,因此,如果 FJ 安排超过 K 只连续的奶牛,那么,这些奶牛就会罢工去开派对:)。现在 FJ 需要你的帮助,计算 FJ 可以得到的最大效率,并且该方案中没有连续的超过 K 只奶牛。

输入

第 1 行:空格隔开的两个整数 N 和 K;
第 2 到 N+1 行:第 i+1 行有一个整数 E_i,表示第 i 只奶牛的效率;

输出

输出共一行一行一个整数,表示 FJ 可以得到的最大的效率值。

f[i]表示不选这头牛前i头牛失去的最小效率值,那么状态转移方程f[i]={f[j]+e[i]},其中i-k≤j<i,显然可以单调队列优化,就不会TLE了。

 1 #include <cstdio>
 2  
 3 struct node{
 4     int pos;
 5     long long v;
 6 }que[100001];
 7  
 8 int l,r,n,k;
 9 long long e[100001],f[100001],sum,ans(99999999999999);
10 #define min(x,y) (x<y?x:y)
11  
12 int main(void){
13     scanf("%d%d",&n,&k);
14     for(int i=1;i<=n;++i){
15         scanf("%lld",&e[i]);
16         sum+=e[i];
17     }
18     for(int i=1;i<=n;++i){
19         f[i]=que[l].v+e[i];
20         while((l<=r)&&(que[l].pos<i-k))++l;
21         while((l<=r)&&(que[r].v>=f[i]))--r;
22         que[++r].pos=i;
23         que[r].v=f[i];
24     }
25     for(int i=n-k;i<=n;++i)
26         ans=min(ans,f[i]);
27     printf("%lld",sum-ans);
28 }

 

posted @ 2018-09-17 22:13  gzh01  阅读(419)  评论(0编辑  收藏  举报