CF467C George and Job 题解 DP 前缀和
DP 前缀和
题意:
给你一个长度为\(n\)的序列,让你从这个序列中挑选出\(k\)个长度为\(m\)的区间,并且任意区间不相交。使得选出的数之和最大,求出这个数。
解法:
很经典的DP模型,我们定义\(f_{i,j}\)表示从前\(i\)个数选出了\(j\)个区间可以取得的最大值,那么答案为:\(f_{n,k}\)。
根据闫式DP分析法,我们可以按照第\(i\)个元素选还是不选来划分。
①不选:结果即为\(f_{i-1,j}\)
②选:结果即为:\(f_{i-m,j-1}+a_{i-m+1}+a_{i-m+2}+...+a_{i-1}+a_{i}\)
用前缀和优化一下:\(f_{i-m,j-1}+s_i-s_{i-m}\)
两种情况取个max即可。
参考代码
void Showball(){
int n,m,k;
cin>>n>>m>>k;
vector<LL> a(n+1),s(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
s[i]=s[i-1]+a[i];
}
vector f(n+1,vector<LL>(k+1));
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
f[i][j]=f[i-1][j];
if(i>=m) f[i][j]=max(f[i][j],f[i-m][j-1]+s[i]-s[i-m]);
}
}
cout<<f[n][k]<<endl;
}