1. 程式人生 > 實用技巧 >Codeforce 基礎dp專題

Codeforce 基礎dp專題

連結:https://codeforces.com/contest/467/problem/C

這道題是求拿k個子序列且不能相交,問如何拿使得這些序列的值的和最大,那麼階段劃分就很明顯了,相當於這道問題對應的隱式DAG上一共可以被分成K層,接著就是列舉在哪個點轉移,也就是是否取當前的往左m的區間,對應的就是在DAG求最短最長路的時候,是從同一層轉移過來還是從前一層轉移過來,取最大最小值貪心,類似dijk的思路。

#include<bits/stdc++.h>
using namespace std;
void check_max (int &a,int b) {a=max (a,b);}
typedef long long ll;
const int maxn=5100;
ll a[maxn];
ll dp[maxn][maxn];
ll pre[maxn];

int main () {
  int n,m,k;
  scanf ("%d%d%d",&n,&m,&k);
  ll st=0;
  for (int i=1;i<=n;i++) {
    scanf ("%lld",&a[i]);
    st+=a[i];
    pre[i]=st;
  }
  memset (dp,0,sizeof (dp));
  // for (int j=m;j<=n;j++) 
  //  for (int i=1;i<=k;i++) {
  //   dp[i][j]=max (dp[i][j-1],dp[i-1][j-m]+pre[j]-pre[j-m]);
  //  }
  for (int i=1;i<=k;i++) 
   for (int j=m;j<=n;j++) {
    dp[i][j]=max (dp[i][j-1],dp[i-1][j-m]+pre[j]-pre[j-m]);
   }
  printf ("%lld\n",dp[k][n]);
  return 0;
}