题意
给你一个序列,你能进行k次操作。其中能进行z次向左操作,但是不能进行连续的向左操作。
思路
转移方程是比较容易想出来的
(dp[i][j])表示在第(i)位时进行(j)次向左操作。
向右:
[dp[i][j]=max(dp[i][j],dp[i-1][j]+a[j])
]
向左:
[dp[i][j]=max(dp[i][j],dp[i+1][j-1]+a[j])
]
根据状态转移方程可以定出循环。
然后在循环中判断条件为步数是否小于等于k,然后dp求解,更新ans。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '
'
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(case, x) cout << case << " : " << x << endl
#define open freopen("ii.txt", "r", stdin)
#define close freopen("oo.txt", "w", stdout)
#define IO
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0)
#define pb push_back
using namespace std;
//#define int long long
#define lson rt << 1
#define rson rt << 1 | 1
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<long long, long long> PII;
const int maxn = 1e5 + 10;
ll a[maxn], dp[maxn][6];
void solve(){
int n, k, z;
cin >> n >> k >> z;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
dp[i][0] = dp[i - 1][0] + a[i];
for (int j = 1; j <= z; ++j) dp[i][j] = 0;
}
//dp[i][j]=max(dp[i][j],dp[i-1][j]+a[j]);
//dp[i][j]=max(dp[i][j],dp[i+1][j-1]+a[j]);
ll ans = dp[k + 1][0];
for (int j = 1; j <= z;++j){
for (int i = 1; i <= n;++i){
if(2*j+i-1<=k){
dp[i][j] = max(dp[i][j], dp[i - 1][j] + a[i]);
dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + a[i]);
}
ans = max(dp[i][j], ans);
}
}
cout << ans << endl;
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
return 0;
}