URAL 1146. Maximum Sum[DP最大子矩阵和]

1146. Maximum Sum

Time limit: 0.5 second
Memory limit: 64 MB
Given a 2-dimensional array of positive and negative integers, find the sub-rectangle with the largest sum. 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. A sub-rectangle is any contiguous sub-array of size 1 × 1 or greater located within the whole array.
As an example, the maximal sub-rectangle of the array:
0−2−70
92−62
−41−41
−180−2
is in the lower-left-hand corner and has the 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 white-space (newlines and spaces). These  N  2 integers make up the array in row-major order (i.e., all numbers on the first row, left-to-right, then all numbers on 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

The output is the sum of the maximal sub-rectangle.

Sample

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

© 2000–2017 Timus Online Judge Team. All rights reserved.

求最大子矩阵和,直接枚举四个端点时间复杂度有点大,所以转换成最大字段和,

sum[i][j]保存第i行第j列中前j个的和。。。。

枚举上下行r1,r2,然后就是求最大字段和啦。。。

#include<bits/stdc++.h>
#define ll long long

using namespace std;
const int maxn = 1e2+7;

int n, m[maxn][maxn], sum[maxn][maxn];

void clomn()
{
    memset(sum, 0, sizeof(sum));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
           sum[i][j] = sum[i - 1][j] + m[i][j];
}

int solve()
{
    clomn();
    int ans = -10000;
    for(int r1 = 1; r1 <= n; r1++)
        for(int r2 = r1; r2 <= n; r2++)
        {
            int t = 0;
            for(int i = 1; i <= n; i++)
            {
                t += sum[r2][i] - sum[r1 - 1][i];
                ans = max(t, ans);
                if(t < 0) t = 0;
            }
        }
    return ans;
}


int main()
{
    //freopen("in.txt", "r", stdin);
    while(~scanf("%d",&n))
    {
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++) scanf("%d",&m[i][j]);
        printf("%d\n", solve());
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值