您的位置:首页 > 其它

TK题库 1133 最大子阵和(动态规划DP 最大字段和)

2017-08-12 10:26 337 查看

原题

 最大子阵和

时间限制: 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]。

输出

输出最大子阵和。

样例输入

4

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2

样例输出

15

涉及知识及算法

首先,这个子矩阵可以是任意大小的,而且起始点也可以在任何地方,所以,要把最大子矩阵找出来,我们要考虑多种情况。

假定原始矩阵的行数为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] 得到。

代码

#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,表示感谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息