Gym 101873I - Uberwatch - [DP]

題目連接: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]);
}
相關文章
相關標籤/搜索