【题目链接】
终于A了这题了。
m = 1和m = 2两种情况分开做。
对于m = 1,很简单的DP。设dp[k][n]表示前n个数字,分为k段的最大权值。
(1)不取第n个数,dp[k][n] = dp[k][n - 1];
(2)取第n个数,并组成新的一段,dp[k][n] = max{dp[k - 1][j] + sum[n] - sum[j]} (0 <= j < i)
注意j可以取到0。
对于m = 2,也是类似的。设dp[k][n][m]表示第一列到前n个数字,第二列到前m个数字,分为k个子矩阵的最大权值。
(1)不取第n个数或者不取第m个数,dp[k][n][m] = max{dp[k][n - 1][m], dp[k][n][m - 1]}
(2)第k个子矩阵是从第一列第n个数向上延伸的,dp[k][n][m] = max{dp[k - 1][i][m] + sum[n][0] - sum[i][0]} (0 <= i < n),其中sum[n][0]代表第一列的前缀和。
(3)第k个子矩阵是从第二列第m个数向上延伸的,dp[k][n][m] = max{dp[k - 1][n][j] + sum[m][1] - sum[j][1]} (0 <= j < m),其中sum[m][1]代表第二列的前缀和。
(4)当n == m时,第k个子矩阵从n和m同时向上延伸,dp[k][n][m] = max{dp[k - 1][i][i] + sum[n][0] - sum[i][0] + sum[m][1] - sum[i][1]} (0 <= i < n)。
完啦。
/* Pigonometry */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 105, maxk = 12; int n, m, k; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline void solve1() { static int sum[maxn], dp[maxk][maxn]; memset(sum, 0, sizeof(sum)); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + iread(); for(int t = 1; t <= k; t++) for(int i = 1; i <= n; i++) { dp[t][i] = dp[t][i - 1]; for(int j = 0; j < i; j++) dp[t][i] = max(dp[t][i], dp[t - 1][j] + sum[i] - sum[j]); } printf("%d\n", dp[k][n]); } inline void solve2() { static int sum[maxn][2], dp[maxk][maxn][maxn]; memset(sum, 0, sizeof(sum)); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) { sum[i][0] = sum[i - 1][0] + iread(); sum[i][1] = sum[i - 1][1] + iread(); } for(int t = 1; t <= k; t++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { dp[t][i][j] = max(dp[t][i - 1][j], dp[t][i][j - 1]); for(int l = 0; l < i; l++) dp[t][i][j] = max(dp[t][i][j], dp[t - 1][l][j] + sum[i][0] - sum[l][0]); for(int l = 0; l < j; l++) dp[t][i][j] = max(dp[t][i][j], dp[t - 1][i][l] + sum[j][1] - sum[l][1]); if(i == j) for(int l = 0; l < i; l++) dp[t][i][j] = max(dp[t][i][j], dp[t - 1][l][l] + sum[i][0] - sum[l][0] + sum[j][1] - sum[l][1]); } printf("%d\n", dp[k][n][n]); } int main() { n = iread(); m = iread(); k = iread(); if(m == 1) solve1(); else if(m == 2) solve2(); return 0; }