1 条题解

  • 0
    @ 2025-5-11 18:14:50

    算法标签

    动态规划:通过动态规划的方法计算不同子矩形的和,并找出最大和的子矩形,这是解决此问题的核心算法思想。 二维数组处理:对二维数组进行遍历和操作,包括按行处理数组元素以及计算子矩形的和。 枚举:枚举不同的子矩形范围,即枚举所有可能的子矩形来找到最大和的子矩形。

    解题思路

    数据读取:

    首先读取输入的整数 N,它表示二维数组的大小。 接着读取 N^2 个整数,并将它们按行存储在一个 N×N 的二维数组 matrix 中。

    算法核心(最大子矩形和的计算):

    由于子矩形可能从任意行开始,我们需要枚举子矩形的起始行 i 和结束行 j。 对于每一对起始行 i 和结束行 j,我们将这几行的数据压缩成一行(即将这几行对应列的元素相加)。例如,对于一个从第 i 行到第 j 行的子矩形,我们将这 j - i + 1 行的每一列元素相加,得到一个长度为 N 的一维数组 temp。 然后,对这个一维数组 temp 使用动态规划来计算最大子数组和。动态规划的思路是,设 dp[k] 表示以 temp[k] 结尾的最大子数组和,状态转移方程为 dp[k] = max(dp[k - 1] + temp[k], temp[k]),通过遍历 temp 数组得到最大子数组和 max_sum。 在枚举所有可能的起始行 i 和结束行 j 后,我们记录下最大的 max_sum,这个 max_sum 就是最大子矩形的和。

    输出结果:

    最后输出找到的最大子矩形的和。

    代码实现

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,dp[110],a[110][110];
    int Max()
    {
        int b = 0,res=-130;
        for(int i=1;i<=n;i++){
            if(b>0)b+=dp[i];// 表示能如果遇到正数还能继续递增
            else b = dp[i];//如果是负数 由于负数只能越加越小 所以那么直接让他等于当前元素
            res = max(res,b);//最优化结果
        }
        return res;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);
        }
    
        int res=-130;
        for(int i=1;i<=n;i++){
            for(int j = i;j<=n;j++){
                for(int k=1;k<=n;k++)dp[k]+=a[j][k];
                int ma = Max();
                res = max(ma,res);  
            }
            memset(dp,0,sizeof(dp));
        }
    
        printf("%d\n",res);
    
        return 0;
    }
    
    
    • 1

    信息

    ID
    51
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者