1 /* 2 题意:选择k个m长的区间,使得总和最大 3 01背包:dp[i][j] 表示在i的位置选或不选[i-m+1, i]这个区间,当它是第j个区间。 4 01背包思想,状态转移方程:dp[i][j] = max (dp[i-1][j], dp[i-m][j-1] + sum[i] - sum[i-m]); 5 在两个for循环,每一次dp[i][j]的值都要更新 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 #include <cmath> 11 using namespace std; 12 13 typedef long long ll; 14 const int MAXN = 5e3 + 10; 15 const int INF = 0x3f3f3f3f; 16 ll a[MAXN]; 17 ll sum[MAXN]; 18 ll dp[MAXN][MAXN]; 19 20 int main(void) //Codeforces Round #267 (Div. 2) C. George and Job 21 { 22 int n, m, k; 23 while (scanf ("%d%d%d", &n, &m, &k) == 3) 24 { 25 memset (sum, 0, sizeof (sum)); 26 for (int i=1; i<=n; ++i) {scanf ("%I64d", &a[i]); sum[i] = sum[i-1] + a[i];} 27 28 ll ans = 0; 29 for (int i=m; i<=n; ++i) 30 { 31 ll tmp = sum[i] - sum[i-m]; 32 for (int j=1; j<=k; ++j) 33 { 34 dp[i][j] = max (dp[i-1][j], dp[i-m][j-1] + tmp); 35 } 36 ans = max (ans, dp[i][k]); 37 } 38 39 printf ("%I64d\n", ans); 40 } 41 42 43 return 0; 44 } 45 46 /* 47 5 2 1 48 1 2 3 4 5 49 7 1 3 50 2 10 7 18 5 33 0 51 */
时间: 2024-12-21 05:44:40