题目大意:给出一个矩阵,求在这个矩阵中取出k个不重叠的矩阵的最大和。
思路:怎么做?
这个问题困扰我好几天的时间,终于再一次读题:
。。。
。。
。。。
2??!!
这尼玛逗我??直接说最多两列不好么?还用矩阵吓唬我?
好吧下次我一定认真看题。。
我的做法比较渣,算出来的时间复杂度是O(m^3*k),但是只有最多3000w,还是可以过的。
状态:f[i][j][k]表示第一列到了第i个格子,第二列到了第j个格子,已经选取了k个矩阵的最大得数。
转移:先把现有的状态向后转移,转移成f[i'][j'][k],然后取矩阵,向后转移,转移成f[i'][j'][k + 1]。这里要分三种情况讨论,转移第一列,转移第二列,和两列一起转移。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 110
using namespace std;
int m,n,c;
int src[MAX][3],sum[3][MAX];
int f[MAX][MAX][15];
int main()
{
cin >> m >> n >> c;
for(int i = 1; i <= m; ++i)
for(int j = 1; j <= n; ++j) {
scanf("%d",&src[i][j]);
sum[j][i] = sum[j][i - 1] + src[i][j];
}
int ans = 0;
if(n == 1) {
for(int i = 0; i <= m; ++i)
for(int k = 0; k <= c; ++k)
for(int _i = i + 1; _i <= m; ++_i) {
f[_i][k][0] = max(f[_i][k][0],f[i][k][0]);
f[_i][k + 1][0] = max(f[_i][k + 1][0],f[i][k][0] + sum[1][_i] - sum[1][i]);
}
for(int i = 0; i <= m; ++i)
for(int k = 0; k <= c; ++k)
ans = max(ans,f[i][k][0]);
}
else {
for(int i = 0; i <= m; ++i)
for(int j = 0; j <= m; ++j)
for(int k = 0; k <= c; ++k) {
for(int _i = i + 1; _i <= m; ++_i) {
f[_i][j][k] = max(f[_i][j][k],f[i][j][k]);
f[_i][j][k + 1] = max(f[_i][j][k + 1],f[i][j][k] + sum[1][_i] - sum[1][i]);
}
for(int _j = j + 1; _j <= m; ++_j) {
f[i][_j][k] = max(f[i][_j][k],f[i][j][k]);
f[i][_j][k + 1] = max(f[i][_j][k + 1],f[i][j][k] + sum[2][_j] - sum[2][j]);
}
for(int _k = max(i,j) + 1; _k <= m; ++_k) {
f[_k][_k][k] = max(f[_k][_k][k],f[i][j][k]);
f[_k][_k][k + 1] = max(f[_k][_k][k + 1],f[i][j][k] + sum[1][_k] - sum[1][max(i,j)] + sum[2][_k] - sum[2][max(i,j)]);
}
}
for(int i = 0; i <= m; ++i)
for(int j = 0; j <= m; ++j)
for(int k = 0; k <= c; ++k)
ans = max(ans,f[i][j][k]);
}
cout << ans << endl;
return 0;
}