Codeforces Round #267 (Div. 2)(前綴和+二維dp)

C. George and Job

cf原題目地址
vj地址
在這裏插入圖片描述
在這裏插入圖片描述

題意:

給你一個數組,要求你找出最大的k段 長度爲m的區間和並相加。

思路:

數據不大可以二維dp

  1. dp【i】【j】。i: 當前位置, j 表示有幾段和。
  2. for(int i=m, i<=n; i++)
    {
    ll tmp;
    tmp=pre[i]-pre[i-m];
    for(int j=min(i/m,k);j>=1; j–)//枚舉的段數,不能超過當前的i/m,也不能大於k段,因爲最多隻有k段
    {
    dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+tmp);
    }
    }

反思

  1. 一開始的轉移時不嚴謹,只開了一維,沒考慮位置的影響,
  2. 第k個只能從前面的i-k的位置遞推過來。不能簡簡單單的從之前的dp【j-1】遞推
  3. 因爲j-1取得的最大位置可能在【i-k,i】之中,即重合了,所以要多開一維,避免重合

AC

#include <iostream>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
using namespace std;
typedef long long ll;
const int maxn=5e3+10;
ll dp[maxn][maxn];
ll pre[maxn];
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    For(i,1,n)
    {
        ll p;
        cin>>p;
        pre[i]=pre[i-1]+p;
    }
   ll ans=0;
    For(i,m,n)
    {
        ll tmp;
        tmp=pre[i]-pre[i-m];
        for(int j=min(i/m,k);j>=1; j--)
        {
            dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+tmp);
        }
    }
    cout<<dp[n][k]<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章