Acwing 4378.选取数对
题目:
样例:
//题意:从数组里选择K个长度为M的数组求和的最大值
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[5005];
ll sum[5005], w[5005];
ll dp[5005][5005];//dp[i][j]含义:表示可以选择的前i个数组里恰选择j个数组的和的最大值
int main(){
int n, m ,k;
cin>>n>>m>>k;
for(int i = 1; i <= n; i++){
cin>>a[i];
sum[i] = sum[i - 1] + a[i];//前缀和
}
int cnt = 0;
for(int i = 1; i + m - 1 <= n; i++){
w[++cnt] = sum[i + m - 1] - sum[i - 1];//枚举所有可能满足条件的数组
}
//转化为0-1背包问题
for(int i = 1; i <= cnt; i++){
for(int j = 1; j <= k; j++){
if(i - m < 0) dp[i][j] = max(dp[i - 1][j], w[i]);
//i - m < 0 时 最多只能选择一个数组 因为此时选择多于一个数组的话 数组下标会重合
//两种状态 选 :则值只能选择这一个数组也就是w[i] 不选就是去掉当前数组 也就是dp[i - 1][j]
else dp[i][j] = max(dp[i - 1][j], dp[i - m][j - 1] + w[i]);
}
}
cout<<dp[cnt][k]<<endl;
}