最大子矩阵和(To The Max)

 

Given a two - dimensional array of positive and negative integers, a sub - rectangle  is  any contiguous sub - array of size  1  x  1  or greater located within the whole array. The sum of a rectangle  is  the sum of all the elements  in  that rectangle. In  this  problem the sub - rectangle with the largest sum  is  referred to  as  the maximal sub - rectangle.

As an example, the maximal sub
- rectangle of the array:

0   - 2   - 7   0
9   2   - 6   2
- 4   1   - 4   1
- 1   8   0   - 2

is   in  the lower left corner:

9   2
- 4   1
- 1   8

and has a sum of 
15 .

The input consists of an N x N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two
- dimensional array. This  is  followed by N  2  integers separated by whitespace (spaces and newlines). These are the N  2  integers of the array, presented  in  row - major order. That  is , all numbers  in  the first row, left to right, then all numbers  in  the second row, left to right, etc. N may be  as  large  as   100 . The numbers  in  the array will be  in  the range [ - 127 , 127 ].

Output
Output the sum of the maximal sub
- rectangle. 
Sample Input
4
0   - 2   - 7   0  
9   2   - 6   2
- 4   1   - 4   1
- 1   8   0   - 2
Sample Output
15

提交代码如下(仅供参考):

#include  < stdio.h >

#define  MAX 130

int  maxSum( int  b[],  int  n)
{
    
int max = b[0];
    
int sum = 0;
    
for(int i = 0; i < n; ++i)
    
{
        
if(sum < 0) sum = b[i];
        
else sum += b[i];
        
if(sum > max) max = sum;
    }

    
return max;
}


int  solve( int  a[][MAX],  int  n)
{
    
int b[MAX];
    
int i,j,k,sum,tmp;
    sum 
= a[0][0];
    
for(i = 0; i < n; ++i)
    
{
        
for(k = 0; k < n; ++k) b[k] = 0;
        
for(j = i; j < n; ++j)
        
{
            
for(k =0; k < n; ++k) b[k] += a[j][k];
            
if(sum < (tmp = maxSum(b,n)) ) sum = tmp;
        }

    }

    
return sum;
}


int  main()
{
    
int arr[MAX][MAX];
    
int i,j,n;
    
while(scanf("%d",&n)!=EOF)
    
{
        
for(i = 0; i < n; ++i)
            
for(j = 0; j < n; ++j)
                scanf(
"%d",&arr[i][j]);
        printf(
"%d ",solve(arr,n));
    }

    
return 0;
}

最大子矩阵和,即在一个n*m的矩阵中找出其子矩阵其和最大,如果直接枚举每一个子矩阵是不现实的,为了简化计算的过程,可以对矩阵进行转换...

一个子矩阵是由原矩阵中的行列组成,在求解的过程中只要找出其最大的和,在查找一维矩阵(即一维数组)时,求n个元素的和最大的子区间,我们采用的思想是扫描这一维矩阵,用max表示出现的和的最大值,sum表示从左至右的求和的值,我们要考虑sum值出现的情况,如果sum < 0这种求和是没有意义的,因为任何数加上一个小于0的负数其值必然减少,也就是这时是不可能出现最大的值,这样就可以采用将要加上的元素值赋给sum,以该点做为下一个求和的开始...,还有一点就是在使用sum计算求和时,我们只有在扫描所有元素才知道出现子区间和的最大值是什么,也就是只要为sum>0情况则再加上一元素,该元素的值必然会增大,也就是有可能出现sum的值变大出现sum > max的情况,虽然也会出现sum减少的情况,但是我们始终有max记录在求和过程中出现过的最大值,如果max < sum则更新max的值,最终的max便是我们要求的一维矩阵的最大值

 

int  maxSum( int  b[],  int  n)
{
    
int max = b[0];
    
int sum = 0;
    
for(int i = 0; i < n; ++i)
    
{
        
if(sum < 0) sum = b[i];
        
else sum += b[i];
        
if(sum > max) max = sum;
    }

    
return max;
}

有了一维的基础,这样就可以,扩展到二维矩阵,要想一个子矩阵的和值最大,那么其子子矩阵的和必然也是在子矩阵中的和最大的,这样就可以通过将i行转为1行,即将二维矩阵转为一维,这样就可以通过求一维的方法来处理二维的矩阵,使用循环控制子矩阵的开始行位置并累加出以此行产生出的子矩阵的和将i*m的子矩阵转为1*m的子矩阵,使maxSum求出1*m的矩阵中的出现的最大值...

 

for (i  =   0 ; i  <  n;  ++ i)
    
{
        
for(k = 0; k < n; ++k) b[k] = 0;
        
for(j = i; j < n; ++j)
        
{
            
for(k =0; k < n; ++k) b[k] += a[j][k];
            
if(sum < (tmp = maxSum(b,n)) ) sum = tmp;
        }

    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值