最大子矩阵和问题java_【算法设计】最大子矩阵问题

一,最大子矩阵问题:

给定一个n*n(0

Example:

0 -2 -7  0

9  2 -6  2

-4  1 -4  1

-1  8  0 -2

其中左上角的子矩阵:

9 2

-4 1

-1 8

此子矩阵的值为9+2+(-4)+1+(-1)+8=15。

二,分析

子矩阵是在矩阵选取部份行、列所组成的新矩阵。

例如

f800120e4d3d602679128b940acd5f2e.png

e74f3066e283124877a6e687b7c5b25b.png

它亦可用A(3;2)表示,显示除掉第3行和第2列的余下的矩阵。这两种方法比较常用,但还是没有标准的方法表示子矩阵。

以上为维基百科上给出的定义,感觉跟此题的定义不是一回事呢?

我们首先想到的方法就是穷举一个矩阵的所有子矩阵,然而一个n*n的矩阵的子矩阵的个数当n比较大时时一个很大的数字 O(n^2*n^2),显然此方法不可行。怎么使得问题的复杂度降低呢?对了,相信大家应该知道了,用动态规划。对于此题,怎么使用动态规划呢?

请先参考-->最大子段和问题

这个问题与最大子段有什么联系呢?

假设最大子矩阵的结果为从第r行到k行、从第i列到j列的子矩阵,如下所示(ari表示a[r][i],假设数组下标从1开始):

| a11 …… a1i ……a1j ……a1n |

| a21 …… a2i ……a2j ……a2n |

|  .     .     .    .    .     .    .          |

|  .     .     .    .    .     .    .          |

| ar1 …… ari ……arj ……arn    |

|  .     .     .    .    .     .    .          |

|  .     .     .    .    .     .    .          |

| ak1 …… aki ……akj ……akn  |

|  .     .     .    .    .     .    .          |

| an1 …… ani ……anj ……ann |

那么我们将从第r行到第k行的每一行中相同列的加起来,可以得到一个一维数组如下:

(ar1+……+ak1, ar2+……+ak2, ……,arn+……+akn)

由此我们可以看出最后所求的就是此一维数组的最大子段和问题,到此我们已经将问题转化为上面的已经解决了的问题了。

三,源码

C++:

#include

using namespace std;

int maxSubArray(int a[],int n)

{

int b=0,sum=a[0];

for(int i=0;i

{

if(b>0)

b+=a[i];

else

b=a[i];

if(b>sum)

sum=b;

}

return sum;

}

int maxSubMatrix(int array[][3],int n)

{

int i,j,k,max=0,sum=-100000000;

int b[3];

for(i=0;i

{

for(k=0;k

{

b[k]=0;

}

for(j=i;j

{

for(k=0;k

{

b[k]+=array[j][k];

}

max=maxSubArray(b,k);

if(max>sum)

{

sum=max;

}

}

}

return sum;

}

int main()

{

int n=3;

int array[3][3]={{1,2,3},{-1,-2,-3},{4,5,6}};

cout<

}

java:

import java.util.Scanner;

public class PKU_1050

{

private int maxSubArray(int n,int a[])

{

int b=0,sum=-10000000;

for(int i=0;i

{

if(b>0)

b+=a[i];

else

b=a[i];

if(b>sum)

sum=b;

}

return sum;

}

private int maxSubMatrix(int n,int[][] array)

{

int i,j,k,max=0,sum=-100000000;

int b[]=new int[101];

for(i=0;i

{

for(k=0;k

{

b[k]=0;

}

for(j=i;j

{

for(k=0;k

{

b[k]+=array[j][k];

}

max=maxSubArray(k,b);

if(max>sum)

{

sum=max;

}

}

}

return sum;

}

public static void main(String args[])

{

PKU_1050 p=new PKU_1050();

Scanner cin=new Scanner(System.in);

int n=0;

int[][] array=new int[101][101];

while(cin.hasNext())

{

n=cin.nextInt();

for(int i=0;i

{

for(int j=0;j

{

array[i][j]=cin.nextInt();

}

}

System.out.println(p.maxSubMatrix(n,array));

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值