最大子矩阵

本题为基础dp模型学习中的例题之一:

http://t.csdn.cn/gS7CF

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

【题目描述】

已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 × 1)子矩阵。

比如,如下4 × 4的矩阵

0  -2 -7  0
9  2 -6  2
-4  1 -4  1
-1  8  0 -2

的最大子矩阵是

 9 2
-4 1
-1 8

这个子矩阵的大小是15。

【输出】

输出最大子矩阵的大小。

【输入样例】

4
0 -2 -7  0
9  2 -6  2
-4  1 -4  1
-1  8  0 -2

【输出样例】

15

将二维矩阵转换成一维解决 == >> 求行列的最大子序列

例:

思路图:

初始图

1 3
-2 6

数组S[i][j]  == 第j列到第i行的前缀和

1 3
-1 9

而我们的dp数组只需要在[i,j]范围内找到行列中间最大子序列即可

此时只有俩列分别为

-1 9

对dp数组求最大子序列就是最后的答案

最终答案就为8

代码实现:

 通过俩层嵌套枚举n * n矩阵中间所有情况的子矩阵

for(int i = 1;i <= n;i++)
    for(int j = 1;j <= n;j++)

每一轮对于子矩阵[i,j]范围的n列求其前缀和

for(int k = 1;k <= n;k++)
b[k] = s[j][k] - s[i - 1][k];

统计每一轮的dp数组结果 == 最大子序列的实现

for(int k = 1;k <= n;k++)
dp[k] = max(b[k],dp[k - 1] + b[k])

AC代码

#include
using namespace std;
const int maxn = 105;
#define INF 0x3f3f3f3f
int dp[maxn];
int n, a[maxn][maxn], b[maxn], s[maxn][maxn];// b[j]:子矩阵第j列的加和
int ans = -INF;
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            cin >> a[i][j];
            s[i][j] = s[i - 1][j] + a[i][j];//求第j列到第i行的和 
        }//计算列前缀和

    for (int i = 1; i <= n; i++)//每一轮的枚举矩阵范围为[i,j]
        for (int j = i; j <= n; j++)
        {//新一轮的枚举缩小搜索范围
            for (int k = 1; k <= n; k++)//求[i,j]范围内k列的前缀和
                b[k] = s[j][k] - s[i - 1][k]; 
            for (int k = 1; k <= n; k++)
            {//每查找一轮更新一次答案
                dp[k] = max(b[k], dp[k - 1] + b[k]);
                ans = max(ans, dp[k]);
            }
        }
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(洛谷题目集,基础算法学习,矩阵)