最大子阵.java

package A类有价值的回顾的;

import java.util.Scanner;

public class 最大子阵 {

    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);

        int[][] a = new int[505][505];
        int[] b  = new int[505];//降低到一维只有列坐标时
        int[] dp = new int[505];
        int ans = -0x3f3f3f3f  ;//int ans = 0;

        int n = sc.nextInt();
        int m = sc.nextInt();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){//for(int j=1;j<=n;j++){对于这种重复性的东西,最怕的是微小的改变反应不过来,理性的解决问题
                                  //敲完先别急着去验证,先按照思路走一遍,看看有什么遗漏,这样一次成功的可能性会大些,心理压力会小一些
                a[i][j] = sc.nextInt();
            }
        }
        for(int sr=1;sr<=n;sr++){

            for(int i=1;i<b.length;i++){
                b[i] = 0;
            }
            //Arrays.fill(b, 0);
            //for(int i=sr;sr<=n;sr++){

            for(int i=sr;i<=n;i++){

                for(int j=1;j<=m;j++){  
                    b[j] = b[j] + a[i][j];//第j行的所有数都加起来 
                }

                dp[1] = b[1];
                if(dp[1] > ans)
                    ans = dp[1];

                    for(int j=2;j<=m;j++){//最大字段和部分,从二维降低到一维,然后利用已知的知识

                        if(dp[j-1]<0)//首先,正的就是加,负的就是减,这是一个区分 
                                     //如果前j-1项的和小于0,那么就放弃前j-1项吧
                            dp[j] = b[j];//放弃小于0的前几项的dp,重新开始,小于0的绝对没有用
                        else
                            dp[j] = dp[j-1] + b[j];//一个精妙之处就是说,一个最简的代码却考虑了所有的情况



                        if(dp[j]>ans)//这里是一个求最大值的,这个可以剥离来看
                            ans = dp[j];//保存最大值,进入下一层,相当于dp[j-1],这比枚举好多了,想一想人家是怎么改进的
                    }
            }


        }System.out.println(ans);

    }
}
/*
 * 问题描述
  给定一个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。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值