POJ-1050 To the Max 解题报告

POJ - 1050

题目描述

To the Max

Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater located within the whole array. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the maximal sub-rectangle.
As an example, the maximal sub-rectangle of the array:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
is in the lower left corner:
9 2
-4 1
-1 8
and has a sum of 15.

Input

The input consists of an N * N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two-dimensional array. This is followed by N^2 integers separated by whitespace (spaces and newlines). These are the N^2 integers of the array, presented in row-major order. That is, all numbers in the first row, left to right, then all numbers in the second row, left to right, etc. N may be as large as 100. The numbers in the array will be in the range [-127,127].

Output

Output the sum of the maximal sub-rectangle.

Sample Input

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

Sample Output

15

题目大意

题目意思很明白,给定一个矩阵,矩阵最大为100 * 100,矩阵中每个数字的范围为[-127, 127],我们的目标是求一个此矩阵的子矩阵,使得子矩阵中所有元素的和最大。

解题方法

动态规划。
在求解这道题目之前先要弄清楚这道题目:

给定n(1<=n<=100000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。

这道题目的优化解法也是动态规划,在解题过程中有这么几点:

  1. 若某一个元素之前的子段和为负,那此时的最大子段和为此元素。
  2. 我们可能求多个不连续子段,将其中的最大值存到整形变量之中,当发现新的子段和大于max时,修改max,否则,max保持不变,最后返回max。

题目可见此处:LeetCode
AC代码如下

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum = -INT_MAX,b = 0;
        for(int i = 0; i < nums.size(); i ++)
        {
            b = b > 0 ? b + nums[i] : nums[i];
            sum = max(sum, b);
        }
        return sum;
    }
};

回到我们这道题目,差别无非就是把一维数组换成了二维数组。
我们可以这样想,在一个子矩阵中,可以把同一列的元素相加,当作一个元素使用,然后,二维数组中的问题就回归到了一维数组,这样便减小了问题的规模,所以现在的问题就是,遍历这个矩阵,分析所有的子矩阵,求出所需要的max。
用这样的思想,首先将第一行当作一个求最大子段和的问题,求出第一行的最大值,接着,按次序遍历其他行以及连续行组成,即,1,12,123,1234,23,234…
这样用计算得到的最大值不断更新max,就能获得最终解。

代码如下

#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 100;
int a[MAX][MAX];
int b[MAX];
int N;
int main()
{
    cin >> N;
    for(int i = 0; i < N; i ++)
        for(int j = 0; j < N; j ++)
            cin >> a[i][j];
    int sum = -1000000, tem = 0;
    for(int i = 0; i < N; i ++)
        for(int j = i; j < N; j ++)
        {
            if(i == j)
            {
                tem = 0;
                for(int k = 0; k < N; k ++)
                {
                    if(tem > 0)
                        tem += a[i][k];
                    else
                        tem = a[i][k];
                    if(tem > sum)
                        sum = tem;
                }
            }
            else
            {
                memset(b, 0, sizeof(b));
                tem = 0;
                for(int k = 0; k < N; k ++)
                    for(int t = i; t <= j; t ++)
                        b[k] += a[t][k];                
                for(int k = 0; k < N; k ++)
                {
                    if(tem > 0)
                        tem += b[k];
                    else
                        tem = b[k];
                    if(tem > sum)
                        sum = tem;
                }
            }
        }
    cout << sum << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41480330/article/details/82529022
今日推荐