题意:
求最大子矩阵和。其中一个矩阵的和定义为矩阵中所有元素相加的和。
输入:
首先输入一个N,然后输入一个N*N的矩阵
输出:
输出结果即为最大子矩阵和
思路:
本题是一道经典的动态规划题目。可以联想到最大子段和的求解方法。
最大子段和的求解方法:
假设data[]数组存储原始的数据,记res[i]表示包含data[i]元素在内的前i + 1个元素的最大子段和(此子段必须包含data[i]),则有如下递推式
res[i] = max(res[i - 1] + data[i], data[i])
其中,res[0] = data[0]。最大子段和即为max(res[i])
最大子矩阵和的求解思路:
a11 a12 a13
a21 a22 a23
a31 a32 a33
以上面的矩阵为例,先对矩阵的每一行求最大子段和,然后求a11 + a 21, a12 + a22, a13 + a23的最大子段和……最后,求a11 + a21 + a31,a12 + a22 + a32, a13 + a23 + a33的最大字段和, 其中的最大值即为最终结果。其基本思路就是将矩阵进行压缩,将矩阵压缩成一行的字段,从而利用最大子段和的求解方法进行求解。
代码如下:
#include <iostream>
using namespace std;
#define MAXLEN 110 //数组最大长度
#define MINNUM -1000
int DP(int n,int data[]);
int max(int a,int b);
int main()
{
int n = 0;
int data[MAXLEN][MAXLEN] = {0}; //原始数据
int sum[MAXLEN] = {0}; //压缩后的字段
int ans = -1000000; //最终结果
int t = 0;
cin>>n;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
cin>>data[i][j];
}
}
for(int i = 0; i < n; i++) //起始行为第i行
{
for(int p = 0; p < n; p++)
{
sum[p] = 0;
}
for(int k = 0; k < n - i; k++) //总共计算k+1行
{
for(int j = 0; j < n; j++)
{
sum[j] = sum[j] + data[i + k][j];
}
t = DP(n,sum); //压缩后的最大子段和
if(ans < t) //记录最大值
{
ans = t;
}
}
}
cout<<ans<<endl;
return 0;
}
int DP(int n,int data[])
{
//求一串序列的连续子序列的最大和
//res[i]表示在包含data[i]的情况下,前i个元素组成的序列的最大和
int maxsum = data[0];
int res[MAXLEN] = {-10000};
res[0] = data[0];
for(int i = 1; i < n; i++)
{
res[i] = max(res[i - 1] + data[i],data[i]);
if(maxsum < res[i])
{
maxsum = res[i];
}
}
return maxsum;
}
int max(int a,int b)
{
if(a > b)
{
return a;
}
else
{
return b;
}
}