游泳圈的怪胎--最大子矩阵和

来源:互联网 发布:大数据应用 调研 编辑:程序博客网 时间:2024/04/20 01:35
游泳圈的最大子矩阵和

 

Description

二维数组首尾相连,上下也相连,像个游泳圈或轮胎,又如何求最大子矩阵和?
如游泳圈展开成3行3列的二维矩阵:-18 10 71 -20 21 38 -2那么最大的子矩阵和为:10+7+38-2=532 10 71 -20 21 38 -2那么最大的子矩阵和为:10+7+2+38-2+1=56

Input

游泳圈展开成平面数组,第一行是行数m和列数n,第二行至第m+1行是数组数值,每行n个数。

Output

最大的子矩阵和

 

Sample Input

3 32 10 71 -20 21 38 -2

 

Sample Output

56
=====================================================================
我要说的是,这个题目曾经是各大IT公司的一个面试题,可想它是多么的经典。作为学习交流,希望可以给需要的人带去一丝灵感。。以下我将按个人想法分析一下该题目:
游泳圈的最大子矩阵和其实就是把平面上下相连和左右相连。不管先连那边都一样的,一样是O(n^3)。有两种方法:先把游泳圈剪开成平面(随便找一条横边和一条竖边即可),然后原问题等价于把4个这样的平面拼在一起找不超过一个平面大小的最大子矩阵。先用O(n^2)空间转换为1维的问题,枚举上下边界,用一维的方法用单调队列求解。第二种方法比较蛋疼:把游泳圈开一边形成一个环(横的竖的出来结果都一样),假设结果不会越过剪的那条边,于是又是转化为一维的循环数组了。。如果结果越边,还是枚举上下边界转为一维数组的最小子段和。好麻烦,还是第一种方法好。
为了方便编程,我选择第一种方法来解决这个题目。
以下是核心代码仅供参考学习,请勿直接复制提交):
#include "stdio.h"  
#include   
int MaxSum(int n,int* a);
int MaxSum2(int m, int n, int a[][101]);
int main()
{
 int m,n;         
 scanf("%d%d",&m,&n);     
 int temp[101][101]; 
 int result[10000];
 int s[202][202];
 int i,j,p,q;
    memset(temp,0,sizeof(temp));  
 memset(s,0,sizeof(s));  
 memset(result,0,sizeof(result)); 
 //输入二维数组    
 for( i=1; i<=m; i++)            
 for( j=1; j<=n; j++)                         
 {
 scanf("%d",&s[i][j]);  
 s[i][n+j] = s[i][j];
 s[m+i][j] = s[i][j];
 s[m+i][n+j] = s[i][j];
 }
 int r =0;
 for( i=0; i
 for( j=0; j
 {
 for( p=1; p<=m; p++)            
 {
 for(q=1; q<=n; q++)     
 temp[p][q] = s[p+i][q+j];
 }
 result[r++] = MaxSum2(m,n,temp);   //记录各种情况下的最大子矩阵和
 }
   
 int maxresult = result[0]; //从各种情况下的最大子矩阵和中找出最大的值
 for (i=1; i
 {
 if(maxresult < result[i])
 maxresult = result[i];
 }
 printf("%d\n",maxresult);
 return 0; 
}
//用动态规划算法计算“最大子段和问题”,对应于一维数组  
int MaxSum(int n,int* a)
{        
 int sum=0,b=0;                
 for (int i=1;i<=n;i++) 
 {                  
 if (b>0) b+=a[i];                             
 else b=a[i];    
 if (b>sum)  sum=b;         
 }         
 return sum;  
}
int MaxSum2(int m, int n, int a[][101])
{
 int sum=0;        
 int b[101]; 
 int i,j,k,p,t1=0,t2=0;
 memset(b,0,sizeof(b));         //内存空间初始化   
   
 for ( i=1; i<=m; i++)
 {   
 int flag_m = m , flag_n = n;
                
 for( k=1; k<=2*n; k++)
 b[k]=0;   
 for ( j=i; j < flag_m + i; j++) 
 {   
 t1 = j>m? j-m : j;
 for( k=1; k <=n  ; k++) 
 {
 t2 = k>n? k-n : k;
 b[k] += a[t1][t2];      
 } 
 int max = MaxSum(2*n,b);   
 if(max>sum) sum = max;   
                 
 }         
 }      
 return sum;
}


游泳圈最大子矩阵和算法it
喜欢热度
返回首页