算法核心:
先将二维数组处理为一维数组,再对一维数组进行最大连续子序列求和,这里最大连续子序列求和采用的是递推的方法。
算法步骤:
(1)将原矩阵初始化,并创建一个临时二维矩阵,该矩阵的第i行表示的是原矩阵前i行的和;
(2)采用穷举的方法,计算二维矩阵所有可能的连续行的列的和,使其压缩为一维数组;
(3)对步骤(2)中得到的每一个数组进行最大子序列求和,同时,不断更新最大值。
实例以及代码
问题描述:给定一个矩阵,找到最大的子矩阵。
//定义数据,A是原矩阵,t是临时矩阵,用于存储行的和
int A[10][10]={0},t[10][10]={0};
int t1,t2; //一维数组的最大子列和的范围
int l1,l2,h1,h2; //最大子矩阵的范围
//初始化矩阵
int Input(){
int n,i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&A[i][j]);
return n;
}
//计算一个临时的矩阵和矩阵
void Temporary(int n){
int i,j;
for(i=0;i<n;i++)
t[0][i]=A[0][i];
for(i=1;i<n;i++)
for(j=0;j<n;j++)
t[i][j]=A[i][j]+t[i-1][j];
}
//对一维数组进行最大子列求和
int OneSequence(int a[],int n){
int i,sum=0,max=-100;
int s=0,e=0;
for(i=0;i<n;i++)
{
sum=a[i]+sum;
if(max<sum)
{
max=sum;
t1=s;
t2=e;
}
if(sum<0)
{
sum=0;
s=i+1;
e=i+1;
}
else
e++;
}
//printf("%d----%d max=%d",t1,t2,max);
return max;
}
//处理二维矩阵的行,压缩为一维数组
int TwoSequence(int n){
int i,j,k;
int temp[20],max=-100,m;
for(i=-1;i<n;i++)
for(j=0;j<n;j++)
{
if(i<0)
{
for(k=0;k<n;k++)
temp[k]=t[j][k];
}
else
{
for(k=0;k<n;k++)
temp[k]=t[j][k]-t[i][k];
}
m=OneSequence(temp,n); //处理一维数组
if(m>max)
{
max=m;
h1=i;h2=j;
l1=t1;l2=t2;
}
}
return max;
}
//格式化输出
void Output(int max){
int i,j;
printf("最大子矩阵为:\n");
for(i=h1+1;i<=h2;i++) //输出子矩阵
{
for(j=l1;j<=l2;j++)
printf("%d\t",A[i][j]);
printf("\n");
}
printf("最大子矩阵和为:%d",max); //输出 最大和
}
//主函数,负责调用以上函数
int main(){
int n,res;
n=Input();
Temporary(n);
res=TwoSequence(n);
Output(res);
return 0;
}
运行结果: