历届试题 最大子阵

来源:互联网 发布:淘宝网拉杆箱价格图片 编辑:程序博客网 时间:2024/06/05 19:15

问题描述
  给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。

  其中,A的子矩阵指在A中行和列均连续的一块。
输入格式
  输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
  接下来n行,每行m个整数,表示矩阵A。
输出格式
  输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8
样例输出
10
样例说明
  取最后一列,和为10。
数据规模和约定
  对于50%的数据,1<=n, m<=50;
  对于100%的数据,1<=n, m<=500,A中每个元素的绝对值不超过5000。
  


解题思路:
可以转化为求最大子序列 的问题。
第一映像是暴力枚举,不过显然会超时,然后就想到了DP。其实因为矩阵肯定是对齐的,所以如我们将两行加起来求最大子数组就可以得到一个行数为2的子矩阵。所以问题就转化成了求一个数组的最大子数组和。然后就是枚举第i行到第j行相加得到的数组了。注意res的值不能设为0,因为可能最后的结果是负数。
最大子序列和问题的思路在如下链接:
http://blog.csdn.net/qq_30091945/article/details/59113550


Java代码:

import java.util.Arrays;import java.util.Scanner;public class Main {    static int[] dp = new int[600];    static int[][] num = new int[600][600];    static int N;    static int M;    static int MAX = Integer.MIN_VALUE;    public static int GetMax(int m){        int max = dp[1];        int tmp = 0;        for ( int i = 1 ; i <= m ; i++){            if ( tmp > 0 ){                tmp += dp[i];            }else{                tmp = dp[i];            }            max = Math.max(max, tmp);        }        return max;    }    public static void main(String[] args) {        // TODO Auto-generated method stub        Scanner in = new Scanner(System.in);        N = in.nextInt();        M = in.nextInt();        for (int i = 1 ; i <= N ; i++){            for(int j = 1 ; j <= M ; j++){                num[i][j] = in.nextInt();            }        }        for ( int i = 1 ; i <= N ; i++){            Arrays.fill(dp, 0);            for ( int j = i ; j <= N ; j++){                for ( int k = 1 ; k <= M ; k++){                    dp[k] += num[j][k];                }                MAX = Math.max(MAX, GetMax(M));            }        }        System.out.print(MAX);        in.close();    }}

这里写图片描述
(PS:永远解决不了的问题,Java永远要超时,给那些参加蓝桥杯的同学们,不要学我一样学Java了,尽量用C++吧。)

1 0