zoukankan      html  css  js  c++  java
  • [原创]北大ACM POJ 1050题解

    [原创]北大ACM POJ 1050题解

    这题是一维最大子段和的扩展。最大子段和的问题在编程珍珠这本书上讲的很透彻,最优算法的复杂度只要O(N),基本思想就是边扫描数据边累加,如果累加的和小于0,则重置累加和为0并继续扫描后面的数,最后累加和最大的那个就是最大子段和。

    对于本题矩阵情况,可以将其转换为一维来计算,方法就是对任意连续几行进行压缩。比如对矩阵a的第i行到第j行的压缩就是计算第i行到第j行的每列的和,这样就转换成只有1行列和了,这样就可以用一维的方法进行计算了。

    例如
    0 -2 -7 0
    9 2 -6 2
    -4 1 -4 1
    -1 8 0 -2
    取i=0,j=2,则表示0~1行的子矩阵,用colsum[k][j]表示第k列的前j(0,1...,j-1行)的列和
    则0~1行的子矩阵转换成列和的方法就是colsum[k][j]-colsum[k][i]。结果为9,0,-13,2.然后对该列和求最大子段和。通过遍历所有可能的连续行子矩阵,最后得到最大的那个即为最大子矩阵和。由于遍历需要O(N^2)时间,因此该算法总的复杂度为O(N^3)

    代码如下:

    Problem: 1050        User: absolute
    Memory: 280K        Time: 16MS
    Language: C++        Result: Accepted
    #include <stdio.h>
    int main(int argc, char* argv[])
    {
    int n,i,j,k;
    scanf("%d",&n);
    int a[100][100];
    for(i=0;i<n;i++)
    {
    for(j=0;j<n;j++)
    scanf("%d",&a[i][j]);
    }
    //colsum[i][j]表示第i列前j行的和
    int colsum[101][101]={0};
    int maxsub = 0;
    for(i=0;i<n;i++)
    {
    for(j=i+1;j<n+1;j++)
    {
    //计算第i行到第j行(不含第j行)的子矩阵的最大列子段和
    int curmax=0,sum=0;
    for(k=0;k<n;k++)
    {
    colsum[k][j] = colsum[k][j-1]+a[k][j-1];
    sum+=colsum[k][j]-colsum[k][i];
    if(sum<0)
    sum=0;
    if(sum>curmax)
    curmax = sum;

    }
    if(curmax>maxsub)
    maxsub=curmax;
    }
    }
    printf("%d\n",maxsub);
    return 0;
    }
  • 相关阅读:
    解决计算机改名无法连接TFS的问题
    MysqlHelper使用反射机制智能推算数据类型以及属性名称
    Cakephp中使用JavaScriptHelper来引入js文件
    CakePHP程序员必须知道的21条技巧
    cakephp文件结构
    去掉字符串前后所有空格
    小程序 支持html富文本吗
    2018年五月博客整理
    Angular cookies
    webstorm 快捷键
  • 原文地址:https://www.cnblogs.com/absolute8511/p/1649576.html
Copyright © 2011-2022 走看看