最大二位子数组和问题(homework-02)

  前面已经谈过最大一维子数组和问题,这里面扩展到二维。

  一. 常规情况,一个矩形的数组,找到一个矩形的子数组有最大的元素和,求这个和。

  1. 从朴素算法入手,枚举矩形数组的4个顶点,以此计算其数组和。同样,时间复杂度很大,我们仅以此入手逐步优化。

  2. 参照一维数组的思路,保存中间结果,利用动态规划优化算法。优化点就是子数组求和一处,二维数组的求和不同于一维,但是仍然能找到方法:

    先声明这个方法是参考《编程之美》书中的讲解的,鄙人大脑迟钝,尚无法独创:

    令二维数组的起点不是0,而是1,使用PS[i][j]表示以[0][0], [i][0], [0][j], [i][j]四个顶点围起来的子数组和,边界上的PS[*][0]和PS[0][*]全置零。则有:

      PS[i][j] = PS[i - 1][j] + PS[i][j - 1] - PS[i - 1][j - 1] + A[i][j]

      其中,A为整个二维数组,Row_num, Clm_num分别为数组行数、列数。

void cal_PS(){
    int i, j;
    for (i = 0; i <= Row_num; i++){
        PS[i][0] = 0;
    }
    for (j = 0; j <= Clm_num; j++){
        PS[0][j] = 0;
    }
    for (i = 1; i <= Row_num; i++){
        for (j = 1; j <= Clm_num; j++){
            PS[i][j] = PS[i - 1][j] + PS[i][j - 1] - PS[i - 1][j - 1] + A[i][j];
        }
    }
}

    上面的函数处理了部分和,这部分时间复杂度O(Row_num2 * Clm_num2).

   3. 有了部分和,下面寻找最大和的数组。我们的核心思路是把未知问题归结到已知的一维问题上。即,首先循环二维子数组数组的上下界,在每个上下界确定的情况下,用一维数组的方    法确定其左右边界。形象一点说,就是先假定数组上下界已知,然后把每一列上的元素压扁,变成一维的。BC(a, c, j)就是a, c两行之间第j列元素加在一起的和。

      核心部分如下:

 1 int MaxSum_mode1(){
 2     int maximum = -2147483648;// 一个足够小的int值
 3     int Start, All;
 4     for (int a = 1; a <= Row_num; a++){//起始行
 5         for (int c = a; c <= Row_num; c++){ //终结行
 6             Start = BC(a, c, Clm_num);
 7             All = Start;
 8             for (int i = Clm_num; i >= 1; i--){
 9                 if(Start < 0)
10                     Start = 0;
11                 Start += BC(a, c, i);
12                 if(Start > All)
13                     All = Start;
14             }
15             if(All > maximum)
16                 maximum = All;
17         }
18         return maximum;
19     }
20 }

       至此,我们完成了新问题的求解和优化,时间复杂度 O(Row_num2 * Clm_num)

 

先写这么多,我先把扩展问题搞一搞再写别的 T_T

 

posted @ 2013-10-01 11:38  Shone JIN  阅读(127)  评论(0编辑  收藏  举报