题目链接:
Problem - D - Codeforceshttps://codeforces.com/contest/1796/problem/D
题意:
选择k个不同位置+x,其他位置-x,求最大字段和
动态规划
我们设dp表示以i为结尾的最大字段和并且选择j个位置+x
那么我们可以分成三种情况
当 j = 0 时,即所有位置都不选,那么就是所有位置都减去x,根据常规的最大字段和dp即可,dp(i,j) = max(A[i] - x ,A[i]-x+dp(i-1,j))
接下来我们考虑取第i个位置的情况 ,那么如果前面i - 1结尾的字段和大于0那么取dp(i-1,j-1)一定是最优的,否则我们从0开始,可以得出 dp(i,j) = max(0,dp(i-1,j-1)) + A[i] +x
考虑不取第i个位置的情况,当前位置是需要 - x 的,那么dp(i,j) = max(0,dp(i-1,j)) + A[i] - x ,需要注意的是如果 i == j 时,此时是不合法的,因为当前不取的话,前i - 1个数字不可能选择 j个数
AC代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int a[N];
int dp[N][25];
void solve(){
int n,k,x;
cin>>n>>k>>x;
for(int i=1;i<=n;i++){
cin>>a[i];
for(int j=0;j<=k;j++){
dp[i][j]=0;
}
}
int ans=-0;
for(int i=1;i<=n;i++){
for(int j=max(k-n+i,0ll);j<=min(i,k);j++){
if(j==0){
dp[i][j]=max(a[i]-x,a[i]-x+dp[i-1][j]);
}
else {
dp[i][j]=max(0ll,dp[i-1][j-1])+a[i]+x;
if(j<i){
dp[i][j]=max(max(0ll,dp[i-1][j])+a[i]-x,dp[i][j]);
}
}
ans=max(ans,dp[i][j]);
}
}
cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
}