codility上的问题 (20) Tau 2012

这个题目不难,给定一个m行n列的矩阵,我们认为矩阵是循环的,也就是说第0列和第(n - 1)列是相邻的,第0行和第(m - 1)行是相邻的。求最大子阵和……

数据范围:m.n [1..100],矩阵中每个整数[-10000, +10000]。 要求复杂度O(m^3 + n ^3) 空间复杂度O(m * n)。

分析: 首先循环最大子段和的问题,我们可以在O(n)时间内解决。因为循环最大子段和等于 max(非循环的最大子段和,总和 - 非循环的最小子段和)。 那么这个问题,我们首先把矩阵复制一下,就是在第(m - 1)行下面再连接一个相同的矩阵。然后我们按列记录s[i][j]表示从第0行到第i行这一列数的总和。 假设我们最终选定的矩阵在某两行之间的话,我们所求的相当于s[]在这两行之间的循环最大子阵和。之所以把矩阵复制了一份是因为上下循环的关系。我们复制一下就可以统一处理。所以以后只要枚举开始的行,枚举行数,再求最大循环子段和就好了。

代码:

// you can also use includes, for example:
// #include <algorithm>

int maximum(vector<int> &a) {
int i, best, end;
    for (i = best = end = 0; i < a.size(); ++i) {
        if (end < 0) {
            end = 0;
        }
        if ((end += a[i]) > best) {
            best = end;
        }
    }
    return best;
}

int solution(const vector< vector<int> > &C) {
    // write your code here...
    int m = C.size(), n = C[0].size(),i,j,k,s,answer;
    vector<vector<int> > a;
    a.resize(m << 1);
    a[0].resize(n, 0);
   	for (i = 1; i <= m; ++i) {
        a[i].resize(n);
        for (j = 0; j < n; ++j) {
            a[i][j] = a[i - 1][j] + C[i - 1][j];
        }
    }
    for (i = 1; i < m; ++i) {
        a[i + m].resize(n);
        for (j = 0; j < n; ++j) {
            a[i + m][j] = a[i + m - 1][j] + C[i - 1][j];
        }
    }
    answer = 0;
    vector<int> b;
    b.resize(n);
    for (i = 1; i <= m; ++i) {  // number of row to choose
        for (j = 1; j <= m; ++j) {  // begin of row
            for (k = 0; k < n; ++k) {
                b[k] = a[j + i - 1][k] - a[j - 1][k];
            }
            answer = max(answer, maximum(b));
            for (k = s = 0; k < n; ++k) {
                s += b[k];
                b[k] = -b[k];
            }
           	answer = max(answer, s + maximum(b));
        }
    }
    return answer;
        
  
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值