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]);
}
相关文章
相关标签/搜索