原题
最大子阵和
时间限制: 1 Sec 内存限制: 32 MB
题目描述
有一个包含正数和负数的二维数组。一个子矩阵是指在该二维数组里,任意相邻的下标是1*1或更大的子数组。一个子矩阵的和是指该子矩阵中所有元素的和。本题中,把具有最大和的子矩阵称为最大子矩阵。例如:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
这个数组的最大子矩阵为:
9 2
-4 1
-1 8
其和为15。
输入
输入包含多组测试数据。每组输入的第一行是一个正整数N(1<=N<=100),表示二维方阵的大小。接下来N行每行输入N个整数,表示数组元素,范围为[-127,127]。输出
输出最大子阵和。样例输入
40 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
样例输出
15涉及知识及算法
首先,这个子矩阵可以是任意大小的,而且起始点也可以在任何地方,所以,要把最大子矩阵找出来,我们要考虑多种情况。
假定原始矩阵的行数为M,那么对于子矩阵,它的行数可以是1到M的任何一个数。
假定原始矩阵的行数为M,那么对于子矩阵,它的行数可以是1到M的任何一个数。
对于一个K行(K < M)的子矩阵,它的第一行可以是原始矩阵的第1行到 M - K + 1 的任意一行。
假设这个最大子矩阵的维数是一维,要找出最大子矩阵, 原理与求“最大子段和问题” 是一样的。
最大子段和问题的递推公式是 b[j]=max{b[j-1]+a[j], a[j]},b[j] 指的是从0开始到j的最大子段和。例子:
假设一个一维子矩阵为:[9, 2, -6, 2], 那么b[] = {9, 11, 5, 7}, 那么最大字段和为11, 如果找最大子矩阵的话,那么这个子矩阵是 [9, 2] 。
但是,原始矩阵可以是二维的。假设原始矩阵是一个3 * n 的矩阵,那么它的子矩阵可以是 1 * k, 2 * k, 3 * k,(1 <= k <= n)。
如果是1 * k,这里有3种情况:子矩阵在第一行,子矩阵在第二行,子矩阵在第三行。
如果是2 * k,这里有两种情况,子矩阵在第一、二行,子矩阵在第二、三行。
如果是3 * k,只有一种情况。
假设这个子矩阵是 2 *k, 也就是说它只有两行,如果我们把这两行上下相加,情况就和求“最大子段和问题” 又是一样的了。
我们要考虑这个子矩阵有可能只有1行,2行,。。。到n行。而在每一种情况下,我们都要把它所对应的矩阵部分上下相加才求局部最大子矩阵。
比如,假设子矩阵是一个3*k的矩阵,而且,它的一行是原始矩阵的第二行,那么,我们就要在
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
里找最大的子矩阵。
如果把它上下相加,我们就变成了 4, 11, -10,1, 从这个数列里可以看出,在这种情况下,最大子矩阵是一个3*2的矩阵,最大和是15.
为了能够在原始矩阵里很快得到从 i 行到 j 行 的上下值之和,我们这里用到了一个辅助矩阵t,它是原始矩阵从上到下加下来的。
如果我们要求第 i 行到第 j 行之间上下值的和,我们可以通过t[j][f] - t[i-1][f] 得到。
如果我们要求第 i 行到第 j 行之间上下值的和,我们可以通过t[j][f] - t[i-1][f] 得到。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN=100;
int N;
//最大字段和数组
int maxSub[MAXN];
//存储原始矩阵
int m[MAXN][MAXN];
//从首行到当前行的和矩阵
int t[MAXN][MAXN];
//从i行到第j行所对应的矩阵上下值的和
int ij[MAXN];
//最大字段和
int maxSubsequence(int a[])
{
int Max=maxSub[0]=a[0];
for(int i=1;i<N;i++)
{
maxSub[i]=(maxSub[i-1]>0)?(maxSub[i-1]+a[i]):a[i];
if(Max<maxSub[i])
{
Max=maxSub[i];
}
}
return Max;
}
int subMaxMatrix()
{
for(int i=1;i<N;i++)
{
for(int j=0;j<N;j++)
{
t[i][j]+=t[i-1][j];
}
}
int Max=-999;
for(int i=0;i<N;i++)
{
for(int j=i;j<N;j++)
{
for(int f=0;f<N;f++)
{
if(i==0)
{
ij[f]=t[j][f];
}
else
{
ij[f]=t[j][f]-t[i-1][f];
}
}
int result=maxSubsequence(ij);
if(result>Max)
{
Max=result;
}
}
}
return Max;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&N)==1)
{
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
scanf("%d",&m[i][j]);
t[i][j]=m[i][j];
}
}
printf("%d\n",subMaxMatrix());
}
return 0;
}
文章转载自CSDN博主beiyeqingteng,链接http://blog.csdn.net/beiyeqingteng/article/details/7056687,表示感谢。