首页 > 代码库 > BZOJ 1084 SCOI2005 最大子矩阵 动态规划
BZOJ 1084 SCOI2005 最大子矩阵 动态规划
题目大意:给出一个矩阵,求在这个矩阵中取出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; }
BZOJ 1084 SCOI2005 最大子矩阵 动态规划
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。