选择数字(动态规划+单调队列)
2016-11-11 09:45
288 查看
选择数字
题目描述:给定一行n个非负整数a[1]..a
。现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择。你的任务是使得选出的数字的和最大。
输入描述:
第一行两个整数n,k
以下n行,每行一个整数表示a[i]。
输出描述:
输出一个值表示答案。
样例输入:
5 2
1
2
3
4
5
样例输出:
12
数据范围及提示:
对于20%的数据,n <= 10
对于另外20%的数据, k = 1
对于60%的数据,n <= 1000
对于100%的数据,1 <= n <= 100000,1 <= k <= n,
0 <= 数字大小 <= 1,000,000,000
思路:
考虑动归,在第i点时,在i-k到i中肯定有一个点j不能选择,即:j为断点。
所以f[i]=max(f[i],f[j-1]+a[j+1]+a[j+2]……a[i])(i-k<=j<=i)
所以维护前缀和,然后方程就变成了
f[i]=max(f[i],f[j-1]+sum[i]-sum[j]) (i-k<=j<=i)
变形一下变成:f[i]=max(f[i],f[j-1]-sum[j])+sum[i] (i-k<=j<=i)
发现max里面的值只与j有关,所以可以用单调队列优化转移。
#include<iostream> #include<cstdio> #define lon long long using namespace std; const int maxn=100010; lon n,k,a[maxn],s[maxn],f[maxn]; lon head,tail=1,d[maxn],q[maxn]; lon que(lon j) { d[j]=f[j-1]-s[j]; while(head<=tail&&d[q[tail]]<d[j]) tail--; q[++tail]=j; while(head<=tail&&q[head]<j-k) head++; return d[q[head]]; } int main() { scanf("%lld%lld",&n,&k); for(lon i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=s[i-1]+a[i]; for(lon i=1;i<=n;i++) { lon t=-10000000000; /*for(lon j=i-k;j<=i;j++) t=max(t,f[j-1]-s[j]);*/ f[i]=que(i)+s[i]; } cout<<f ; return 0; }
相关文章推荐
- codevs3327选择数字(单调队列优化)
- 【洛谷】2034 选择数字 DP+单调队列
- CodeVS3327 选择数字 解题报告【单调队列优化DP】
- codevs 3327 选择数字 单调队列优化DP
- 【动态规划10】单调队列总结
- 【动态规划19】洛谷p3800 Power收集(dp+单调队列)
- 【动态规划\单调队列】逃亡的准备
- HDU 5945 Fxx and game [单调队列+dp]【动态规划】
- POJ2373 Dividing the Path——动态规划+单调队列优化
- BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)
- 【动态规划】【单调队列】最大子序列的和 (max.c/cpp/pas)
- UESTC-594 我要长高(动态规划+单调队列优化)
- BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)
- 洛谷P2900 [USACO08MAR]土地征用Land Acquisition(动态规划,斜率优化,决策单调性,线性规划,单调队列)
- 【单调队列】【动态规划】[CQBZOJ3059]Bead
- 【单调队列】【动态规划】bzoj3831 [Poi2014]Little Bird
- DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)
- ACM 352. 数字游戏(单调队列)
- POJ2559 Largest Rectangle in a Histogram(比动态规划更快的方法——单调队列)
- 【动态规划】【单调队列】tyvj1305 最大子序和