●BZOJ 2442 [Usaco2011 Open]修剪草坪
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=2442
题解:
单调队列优化DP
把问题转化为:从序列里选出一些相邻之间间隔不超过K的数,使得和最小,记为ret。
答案即为 SUM-ret
令DP[i]表示要选i位置的数的总代价。
转移 DP[i]=min(DP[i-K-1]~DP[i-1])+A[i],复杂度O(NK)。
然后用单调队列维护转移的最小值就好了。复杂度O(N)。
代码:
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 100500 #define ll long long using namespace std; ll DP[MAXN],A[MAXN],SUM; int N,K; int main(){ static int pos[MAXN],l,r; scanf("%d%d",&N,&K); for(int i=1;i<=N;i++) scanf("%lld",&A[i]),SUM+=A[i]; l=1; r=1; DP[0]=0; pos[l]=0; for(int i=1;i<=N+1;i++){ while(l<=r&&i-pos[l]>K+1) l++; DP[i]=DP[pos[l]]+A[i]; while(l<=r&&DP[i]<=DP[pos[r]]) r--; pos[++r]=i; } printf("%lld",SUM-DP[N+1]); return 0; }
Do not go gentle into that good night.
Rage, rage against the dying of the light.
————Dylan Thomas