1084: [SCOI2005]最大子矩阵
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2984 Solved: 1490
[Submit][Status][Discuss]
Description
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵
不能相互重叠。
Input
第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的
分值的绝对值不超过32767)。
Output
只有一行为k个子矩阵分值之和最大为多少。
Sample Input
3 2 2
1 -3
2 3
-2 3
1 -3
2 3
-2 3
Sample Output
9
发现最多只有两列,肯定要从这里入手
设$f[i][j][k]$表示第$1$列选了前$i$行,第$2$列选了前$j$行,一共选了$k$次的最大值
转移时考虑选或者不选,要选的话选几列
复杂度$O(n^3k)$
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; char buf[10000000], *ptr = buf - 1; inline int readint(){ int f = 1, n = 0; char ch = *++ptr; while (ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = *++ptr; } while (ch <= '9' && ch >= '0'){ n = (n << 1) + (n << 3) + ch - '0'; ch = *++ptr; } return f * n; } const int maxn = 100 + 10, INF = 0x7f7f7f7f; int N, M, K; int s[maxn], sum[maxn][3]; int f[maxn][11], g[maxn][maxn][11]; void work1(){ s[0] = 0; for(int i = 1; i <= N; i++) s[i] = s[i - 1] + readint(); for(int i = 0; i <= N; i++) for(int k = 1; k <= K; k++) f[i][k] = -INF; for(int i = 1; i <= N; i++) for(int k = 1; k <= K; k++){ f[i][k] = f[i - 1][k]; for(int j = 0; j < i; j++) f[i][k] = max(f[i][k], f[j][k - 1] + s[i] - s[j]); } printf("%d ", f[N][K]); } void work2(){ sum[0][1] = sum[0][2] = 0; for(int i = 1; i <= N; i++){ sum[i][1] = sum[i - 1][1] + readint(); sum[i][2] = sum[i - 1][2] + readint(); } for(int i = 0; i <= N; i++) for(int j = 0; j <= N; j++) for(int k = 1; k <= K; k++) g[i][j][k] = -INF; for(int i = 1; i <= N; i++) for(int j = 1; j <= N; j++) for(int k = 1; k <= K; k++){ g[i][j][k] = max(g[i - 1][j][k], g[i][j - 1][k]); for(int L = 0; L < i; L++) g[i][j][k] = max(g[i][j][k], g[L][j][k - 1] + sum[i][1] - sum[L][1]); for(int L = 0; L < j; L++) g[i][j][k] = max(g[i][j][k], g[i][L][k - 1] + sum[j][2] - sum[L][2]); if(i == j) for(int L = 0; L < i; L++) g[i][j][k] = max(g[i][j][k], g[L][L][k - 1] + sum[i][1] + sum[i][2] - sum[L][1] - sum[L][2]); } printf("%d ", g[N][N][K]); } int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); N = readint(); M = readint(); K = readint(); if(M == 1) work1(); else work2(); return 0; }