Problem:最大的和

这篇博客介绍了如何通过动态规划算法解决寻找二维数组中具有最大和的子矩形的问题。作者给出了一个4x4的矩阵示例,并详细解释了算法思路,包括将二维问题转化为一维视角,利用前缀和进行优化,以及遍历所有可能的子矩形来找到最大和。程序代码使用C++编写,展示了具体的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description

给定一个包含整数的二维矩阵,子矩形是位于整个阵列内的任何大小为 1×1 或更大的连续子阵列。

矩形的总和是该矩形中所有元素的总和。

在这个问题中,具有最大和的子矩形被称为最大子矩形。

例如,下列数组:

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

其最大子矩形为:

9 2
-4 1
-1 8

它拥有最大和 15。

Input Format

输入中将包含一个 N × N 的整数数组。

第一行只输入一个整数 N,表示方形二维数组的大小。

从第二行开始,输入由空格和换行符隔开的 N2 个整数,它们即为二维数组中的 N2 个元素,输入顺序从二维数组的第一行开始向下逐行输入,同一行数据从左向右逐个输入。

数组中的数字会保持在 [−127,127] 的范围内。

Output Format

输出一个整数,代表最大子矩形的总和。

Scope of Data

1 ≤ N ≤ 100

Sample Input

4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

Sample Output

15

Idea

  • 从一维视角看二维,然后利用DP算法解决“一维问题”
    DP状态转换方程:f[i] = max(f[i - 1], 0) + a[i] (这里a[i]的值可用前缀和表示)
    在这里插入图片描述
  • 前缀和
  • 附上大佬解析

Program Code

 #include <iostream>
 #include <algorithm>
 #include <climits>

 using namespace std;

 const int N = 110;

 int n;
 int result = INT_MIN; //初始化结果
 int matrix[N][N];

 int main()
 {
     /*输入数据*/
     cin >> n;
     for(int i = 1; i <= n; ++ i)
     {
         for(int j = 1; j <= n; ++ j)
         {
             cin >> matrix[i][j];
             matrix[i][j] += matrix[i - 1][j]; //前缀和预处理
         }
     }

     /*枚举所有列长为n的二维矩阵,以上、下边界为约束,同时将同一列的元素看作一个整体*/
     for(int i = 1; i <= n; ++ i) //表示上边界
     {
         for(int j = i; j <= n; ++ j) //表示下边界
         {
             int temp = 0;

             /*遍历子矩阵每一列*/
             for(int k = 1; k <= n; ++ k)
             {
                 /*若前k - 1个数的最大和为负,则舍弃(取值为0),否则加上第k列的值*/
                 temp = max(temp, 0) + (matrix[j][k] - matrix[i - 1][k]);
                 result = max(result, temp); //因为temp为前k列的最大和而非整行的最大和,因此每次作比较
             }
         }
     }

     cout << result << endl;

     return 0;
 }
  • If you have any questions,please feel free to communicate with me.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红油曲奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值