争取每天早起一小时写一题emmm
Description
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。
注意:选出的k个子矩阵 不能相互重叠。
Solution
注意到
其实就是两列数字求最大连续子段和的变形
我们可以枚举当前第一列所处位置 i, 第二列所处位置 j, 当前已经取了 k 个矩阵
做 的状态转移
我们可以枚举上一个矩阵的终点位置,然后利用预处理前缀和的思想对每个方案取max
第 k 个取第二列的情况
第 k 个取第一列的情况
i == j, 第 k 个取一个t * 2 的小矩阵
Code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
const int mod = 100000000;
const int N = 5e5 + 5;
typedef long long ll;
const double pi = acos(-1.0);
const double EPS=1e-8;
int a[105][3], sum[105][3];
int dp[105][105][105];
int main() {
int n, m, p;
cin >> n >> m >> p;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> a[i][j];
sum[i][j] = sum[i - 1][j] + a[i][j];
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
for(int k = 1; k <= p; k++) {
dp[i][j][k] = max(dp[i][j - 1][k], dp[i - 1][j][k]);
for(int l = 0; l < j; l++) {
dp[i][j][k] = max(dp[i][l][k - 1] + sum[j][2] - sum[l][2], dp[i][j][k]);
}
for(int l = 0; l < i; l++) {
dp[i][j][k] = max(dp[l][j][k - 1] + sum[i][1] - sum[l][1], dp[i][j][k]);
}
if(i == j) {
for(int l = 0; l < i; l++)
dp[i][j][k] = max(dp[l][l][k - 1] + (sum[i][1] - sum[l][1]) + (sum[j][2] - sum[l][2]), dp[i][j][k]);
}
}
}
}
cout << dp[n][n][p] << "\n";
return 0;
} 
京公网安备 11010502036488号