小组成员:胡佳奇 马翔
上次课堂作业时在前一次一维数组求最大子数组的基础上求二维数组的最大子数组。
首先看到这个问题我们想到的是在前一次的基础上求线性方向上的最大子数组,经过老师的提示,才明白二维数组的子数组包括二维子数组,这个问题就相对线性方向的组数组相对复杂。
我们从多个角度思考这个问题,首先想从最大单一数值入手,最大值附近最有可能出现最大的子数组,从最大值周围的1,2,4,6,8,。。。开始遍历,但是考虑到有可能最大值附近包含太多的负数导致最大数组不在这个周围。
之后我们又想用排除法来做,求出最小数组,依次淘汰,最后剩下最大值,但算法相对复杂。
最后放弃以上各种想法,决定用最保险的穷举法,
主要的就是for循环了,首先是最外层的,先从i=0开始,当j=0时,先将包含a[0][0]的所有子集都遍历一遍,并求出最大值,记录下来,然后是a[0][1],如此循环下去。在循环中利用的是一维数组求最大子集的方法,不同的是在其中加入了for(x=0;x<row;x++),让其可以把下一行也遍历,因为是矩形数组,所以要考虑行和列。
而在遍历过程中,通过比较max的值,让其在每一个数据中找出一个最大的,同时记录下最大值的行长度和列长度以便输出。对于子数组的输出也和一维数组相同,只是改为二维的而已。
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
max=a[i][j];
for(m=1;m<=column-j;m++)
{
sum=0;
length=1;
line=i;
for(x=0;x<row;x++)
{
for(k=j;k<j+m;k++)
{
sum=sum+a[x][k];
}
if(max<=sum)
{
max=sum;
length=m;
line=x;
b[i][j]=max;
c[i][j]=length;
d[i][j]=line;
}
}
}
}
}
程序如下:
#include<iostream>
using namespace std;
#define N 100
int main()
{
int row,column;
int sum,max;
int i,k,j,t,m,x,n,s;
int a[N][N],b[N][N],c[N][N],d[N][N];
int length,line;
cout<<"请输入数组的行数:"<<endl;
cin>>row;
cout<<"请输入数组的列数:"<<endl;
cin>>column;
cout<<"请输入数组元素:"<<endl;
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{ cin>>a[i][j]; }
}
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
max=a[i][j];
for(m=1;m<=column-j;m++)
{
sum=0;
length=1;
line=i;
for(x=0;x<row;x++)
{
for(k=j;k<j+m;k++)
{
sum=sum+a[x][k];
}
if(max<=sum)
{
max=sum;
length=m;
line=x;
b[i][j]=max;
c[i][j]=length;
d[i][j]=line;
}
}
}
}
}
max=b[0][0];
t=0;
n=0;
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
if(max<b[i][j])
{
max=b[i][j];
t=i;
n=j;
}
}
}
cout<<"最大子数组和是:";
cout<<max<<endl;
cout<<"子序列为"<<endl;
for(i=t;i<=d[t][n];i++)
{
for(j=n;j<n+c[t][n];j++)
{ cout<<a[i][j]<<'\t'; }
cout<<endl;
}
return 0;
}