[BZOJ]1084 [SCOI2005] 最大子矩阵 DP

来源:互联网 发布:单片机仿真软件百度云 编辑:程序博客网 时间:2024/05/21 16:59

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2978  Solved: 1489
[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

Sample Output

9

HINT

Source

[Submit][Status][Discuss]


HOME Back

这道题是简单的DP, 因为m只有2.  f[i][j][k]表示第一行前i个第二行前j个取k个的最大值. 这个可以由枚举i, j, k之后, 枚举第一行在i结尾的矩阵(就是个条), 再枚举第二行在j结尾的矩阵, 然后i==j时就结尾在i的两行的矩阵.  看看代码就懂了.

#include<stdio.h>#include<algorithm>using namespace std;int n, m, K, f[105][105][11], sum[105][105];int main(){scanf("%d%d%d", &n, &m, &K);for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j) scanf("%d", &sum[i][j]), sum[i][j] += sum[i - 1][j];if(m == 1){for(int i = 1; i <= n; ++i)for(int k = 1; k <= K && k <= i; ++k){f[i][0][k] = f[i - 1][0][k];for(int j = k - 1; j < i; ++j)f[i][0][k] = max(f[i][0][k], f[j][0][k - 1] + sum[i][1] - sum[j][1]);}printf("%d\n", f[n][0][K]);}else{for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)for(int k = 1; k <= K; ++k){f[i][j][k] = max(f[i - 1][j][k], f[i][j - 1][k]);for(int p = k-1;p < i;++p)f[i][j][k]=max(f[i][j][k], f[p][j][k - 1] + sum[i][1] - sum[p][1]);for(int p = k-1;p < j;++p)f[i][j][k]=max(f[i][j][k], f[i][p][k - 1] + sum[j][2] - sum[p][2]);if(i == j) for(int p = k - 1; p < i; ++p) f[i][j][k] = max(f[i][j][k],  f[p][p][k - 1] + sum[i][1] - sum[p][1] + sum[j][2] - sum[p][2]);}printf("%d\n", f[n][n][K]);}}