題目連接:http://codeforces.com/gym/101873/problem/Ic++
題意:spa
給出 $n(1 \le n \le 300000)$ 個單位時間,每一個單位時間給出一個 $x_i(0 \le x_i \le 32)$ 表明該單位時間內視野內的敵人數目。code
如今你有一個終極武器,每次使用能夠消滅視野內全部敵人,可是須要 $m$ 個單位時間進行充能,且剛開始該武器是沒有充能的。blog
這意味着,第一次能夠使用該武器是在第 $m+1$ 個單位時間內,而日後若在第 $i$ 個單位時間使用則下一次使用最先能夠在 $m+i$。ci
求出最多能夠消滅的敵人數目。get
題解:it
假設 $dp[i]$ 表示前 $i$ 個單位時間內能消滅的最多的敵人數目。class
狀態轉移方程:$dp[i]=\max\left ( \max\{dp[j]+x[i] | 1 \le j \le i-m\},\max\{dp[j] | i-m+1 \le j < i\} \right )$。im
若是用純暴力dp的話是會超時的,觀察式子,不妨維護 $mx[i] = max\{dp[1],dp[2], \cdots, dp[i]\}$,img
則狀態轉移方程變爲 $dp[i] = \max \left ( mx[i-m] + x[i], mx[i-1] \right )$。
AC代碼:
#include<bits/stdc++.h> using namespace std; const int maxn=3e5+10; int n,m,x[maxn]; int dp[maxn],mx[maxn]; int main() { cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&x[i]); if(n<=m) { printf("0\n"); return 0; } for(int i=1;i<=m;i++) mx[i]=dp[i]=0; for(int i=m+1;i<=n;i++) { dp[i]=max(mx[i-m]+x[i],mx[i-1]); //求得dp[i] mx[i]=max(dp[i],mx[i-1]); //更新mx[i] } printf("%d\n",dp[n]); }