标签:
题目:如何求出一个二维数组中的最大子数组之和。
图一 图二
方案三:其实我们仔细的想一想,就可以发现,它的最简单的原型是求一维数组中的最大值。那么基于这个启发,我们可以把问题从二维转化为一维以提高算法性能。假设已经确定了矩阵区域的上下边界,知道矩阵区域的上下边界分布是第a行和第c行,就把每列的第a行和第c行之间的元素看成一个整体。即求数组:(merge[1],merge[2],merge[3]....).merge[i]=arr[a][i]+arr[b][i]+..+arr[c][i].
这样我们可以枚举矩形的上下边界,然后再用一维情况下的方法确定左右边界,相当于一维数组中的一个元素(通过子矩阵部分和可以在O(1)时间内计算出整体之和),就可以得到二维问题的解。新方法的时间复杂度为:O(N*N*M)=O(N*N*N)。具体过程如下图三所示:
图三
方案一的具体实现代码:int arr[N][M];
int Max(int x,int y)//得到最大值;
{
return (x>y)?x:y;
}
int Sum(int imin,int imax,int jmin,int jmax)//得到子矩阵的和,时间复杂度为O(N*N);
{
int sum=0;
for(int i=imin;i<=imax;i++)
for(int j=jmin;j<jmax;j++)
sum+=arr[i][j];
return sum;
}
int MaxSum(int *arr,int m,int n) //得到子矩阵的最大值;
{
int maximum=0;
for(int i_min=1;i_min<=n;i_min++)
for(int i_max=i_min;i_max<=n;i_max++)
for(int j_min=1;j_min<=m;j_max++)
for(int j_max=j_min;j_max<=m;j_max++)
maximum=Max(maximum,Sum(i_min,i_max,j_min,j_max));
return maximum;
}方案二的具体实现代码:int arr[N][M];
int Sum[N][M];//存储部分和的数组;
int Max(int x,int y)//得到最大值;
{
return (x>y) ? x:y;
}
void GetSum()//预处理得到部分和;
{
for(int i=0;i<=n;i++)
Sum[i][0]=0;//边界值;
for(int j=0;j<=n;j++)
Sum[0][j]=0;//边界值;真正的部分和数据是从Sum[1][1]开始的;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
Sum[i][j]=Sum[i-1][j]+Sum[i][j-1]-Sum[i-1][j-1]+arr[i][j]
}
inline int Sum(int i_min,int i_max,int j_min,int j_max)//调用比较频繁,可设置为内联函数,提高效率。和方案一相比,其时间复杂度为O(1).
{
return Sum[i_max][j_max]-Sum[i_min-1][j_max]-Sum[i_max][j_min-1]+Sum[i_min-1][j_min-1];
}
int MaxSum(int *arr,int m,int n)
{
int maximum=0;
for(int i_min=1;i_min<=n;i_min++)
for(int i_max=i_min;i_max<=n;i_max++)
for(int j_min=1;j_min<=m;j_max++)
for(int j_max=j_min;j_max<=m;j_max++)
maximum=Max(maximum,Sum(i_min,i_max,j_min,j_max));
return maximum;
}方案三的具体实现代码:#include <iostream>
#include <algorithm>
using namespace std;
#define LEN 888
int arr[LEN][LEN];
long long Sum[LEN][LEN];
inline long long MatrixSum(int s, int t, int i, int j)
{
return Sum[i][j]-Sum[i][t-1]-Sum[s-1][j]+Sum[s-1][t-1];
}
int main()
{
int row, col, i, j;
cout<<"please input the row and col of the array:"<<endl;
cin >> row >> col;
cout<<"please input the data of the array:"<<endl;
for (i=1; i<=row; i++) //输入数据;
for (j=1; j<=col; j++)
cin >> arr[i][j];
for (i=0; i<=row; i++) //设置边界线;
Sum[i][0] = 0;
for (j=0; j<=col; j++)
Sum[0][j] = 0;
for (i=1; i<=row; i++) // 预处理计算矩阵的部分和
for (j=1; j<=col; j++)
Sum[i][j] = arr[i][j]+Sum[i-1][j]+Sum[i][j-1]-Sum[i-1][j-1];
int a, c;
long long MaxSum = arr[1][1]; //初始值的设置;
for (a=1; a<=row; a++)
for (c=a; c<=col; c++) // 将子矩阵上下边界设为第a行和第c行,求取取最大值
{
long long Tail = MatrixSum(a, 1, c, 1); //合并列;
for (j=2; j<=col; j++) //按一维数组向后枚举;
{
Tail = max( MatrixSum(a, j, c, j), MatrixSum(a, j, c, j)+Tail);
MaxSum = max(Tail, MaxSum);
}
}
cout <<"最大的子矩阵和为:"<< MaxSum<<endl;
system("pause");
return 0;
} 运行结果如下:#include <iostream>
#include <algorithm>
using namespace std;
#define LEN 1003
int arr[LEN][LEN];
long long Sum[LEN][LEN];
inline long long MatrixSum(int s, int t, int i, int j)
{
return Sum[i][j]-Sum[i][t-1]-Sum[s-1][j]+Sum[s-1][t-1];
}
int main()
{
int row, col, i, j;
cout<<"please input the row and col of the array:"<<endl;
cin >> row >> col;
cout<<"please input the data of the array:"<<endl;
for (i=1; i<=row; i++)
for (j=1; j<=col; j++)
cin >> arr[i][j];
for (i=0; i<=row; i++)
Sum[i][0] = 0;
for (j=0; j<=col; j++)
Sum[0][j] = 0;
// 计算矩阵的部分和
for (i=1; i<=row; i++) //计算部分和;
for (j=1; j<=col; j++)
Sum[i][j] = arr[i][j]+Sum[i-1][j]+Sum[i][j-1]-Sum[i-1][j-1];
int a, c;
long long MaxSum = arr[1][1]; // 上下边界不会跨过第n行和第1行
for (a=1; a<=row; a++)
for (c=a; c<=row; c++)
{
// 将子矩阵上下边界设为第a行和第c行
// 左右边界不会跨过第m列和第1列
long long Tail = MatrixSum(a, 1, c, 1);
for (j=2; j<=col; j++)
{
Tail = max(MatrixSum(a, j, c, j),
MatrixSum(a, j, c, j)+Tail);
MaxSum = max(Tail, MaxSum);
}
long long Sum = MatrixSum(a, 1, c, 1); // 左右边界会跨过第n列和第1列
long long Start = Sum;
int sind = 1;
for (i=2; i<=col; i++)
{
Sum += MatrixSum(a, i, c, i);
if (Sum > Start) {Start = Sum; sind = i;}
}
Tail = MatrixSum(a, col, c, col);
int tind = col;
for (j=col-1; j>=1; j--)
{
Sum += MatrixSum(a, j, c, j);
if (Sum > Tail) {Tail = Sum; tind = j;}
}
if (sind<tind && Start+Tail>MaxSum)
MaxSum = Start+Tail;
}
cout <<"最大的子矩阵和为:"<< MaxSum<<endl;
system("pause");
return 0;
} 扩展问题2:求3维矩阵,也就是长方体中子长方体的最大值?#include <iostream>
#include <algorithm>
using namespace std;
#define LEN 500
int arr[LEN][LEN][LEN];
int Sum[LEN][LEN][LEN];
inline int MaxCubeSum(int a, int b, int c, int d, int i, int j)
{
return Sum[b][d][j]-Sum[a-1][d][j]-Sum[b][c-1][j]-Sum[b][d][i-1]+
Sum[a-1][c-1][j]+Sum[a-1][d][i-1]+Sum[b][c-1][i-1]-Sum[a-1][c-1][i-1];
}
int main()
{
int row, col, high, i, j, k;
cout<<"please input the row, col and high of the array:"<<endl;
cin >> row >> col >>high;
cout<<"please input the data of the array:"<<endl;
for (i=1; i<=row; i++)
for (j=1; j<=col; j++)
for (k=1; k<=high; k++)
cin >> arr[i][j][k];
for (i=0; i<=row; i++)
for (j=0; j<=col; j++)
Sum[i][j][0] = 0;
for (i=0; i<=row; i++)
for (k=0; k<=high; k++)
Sum[i][0][k] = 0;
for (j=0; j<=col ; j++)
for (k=0; k<=high; k++)
Sum[0][j][k] = 0;
// 计算长方体的部分和
for (i=1; i<=row; i++)
for (j=1; j<=col; j++)
for (k=1; k<=high; k++)
Sum[i][j][k] = arr[i][j][k]+Sum[i-1][j][k]+Sum[i][j-1][k]+Sum[i][j][k-1]-Sum[i-1][j-1][k]-Sum[i-1][j][k-1]-Sum[i][j-1][k-1]+Sum[i-1][j-1][k-1];
int a, b, c, d;
int MaxSum = arr[1][1][1];
// 限制第一维的取值范围
for (a=1; a<=row; a++)
for (b=a; b<=row; b++)
// 限制第二维的取值范围
for (c=1; c<=col; c++)
for (d=c; d<=col; d++)
{
// 只剩下最后一维没有确定,利用一维部分和的方法
int Tail = MaxCubeSum(a,b,c,d,1,1);
for (j=2; j<=k; j++)
{
int cur = MaxCubeSum(a,b,c,d,j,j);
Tail = max(Tail+cur, cur);
MaxSum = max(Tail, MaxSum);
}
}
cout <<"最大的子矩阵和为:"<< MaxSum<<endl;
system("pause");
return 0;
} 标签:
原文地址:http://blog.csdn.net/gogokongyin/article/details/51889814