zoukankan      html  css  js  c++  java
  • 51Nod--1051最大子矩阵和(DP入门)


    分析: 我们已经解决了一维的问题(基础篇中的最大子段和问题),现在变成二维了,我们看看能不能把这个问题转化为一维的问题。最后子矩阵一定是在某两行之间的。假设我们认为子矩阵在第i行和第j列之间,我们如何得到i和j呢,对,枚举。  枚举所有1<=i<=j<=M,表示最终子矩阵选取的行范围。

    我们把每一列第i行到第j行之间的和求出来,形成一个数组c,于是一个第i行到第j行之间的最大子矩阵和对应于这个和数组c的最大子段和。于是,我们的算法变为:
     
    我们看看标为红色的部分 就是求每列第i行到第j行之间的所有数的和,我们没有再用一个循环求,而是随着j的增长,每次把第j行的结果叠加到之前的和上。 另外求c的最大子数组和是个线性时间算法,实际上它可以和那个k的for循环合并在一起,不过不影响时间复杂度。时间复杂度是O(M^2N)。
    最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。

    输入

    第1行:M和N,中间用空格隔开(2 <= M,N <= 500)。
    第2 - N + 1行:矩阵中的元素,每行M个数,中间用空格隔开。(-10^9 <= M[i] <= 10^9)

    输出

    输出和的最大值。如果所有数都是负数,就输出0。

    输入示例

    3 3
    -1 3 -1
    2 -1 3
    -3 1 2

    输出示例

    7


    解题思路:

    把从i行到j行的数据按照列的顺序加和,得到一个数组,相当于进行了矩阵压缩。这样就转化为一维的最大子段和问题,会比较容易求解,和最大值比较,得到最后的结果。写的粗略了点,但是还是可以看得懂的,有时间再补充一个完全版的。


    源代码:

    <pre name="code" class="cpp">#include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<string>
    #include<iomanip>
    #include<cstdlib>
    #include<cmath>
    #include<sstream>
    #include<ctime>
    using namespace std;
    
    typedef long long ll;
    #define INF -0x3f3f3f3f;
    
    ll d[505][505];
    ll result[505];
    int M,N;
    
    void getSubMaxMatrix()
    {
        int i,j,k;
        ll maxSubMaxMartix = INF;
        ll temp = 0;
        memset(result,0,sizeof(result));
        for(i = 0 ; i < N; i++)//第i行
        {
            for(j = i; j < N; j++)//第j行
            {
                temp = 0;//每次压缩一维数组后用于计算最大子段和的临时变量
                for(k = 0; k < M; k++)
                {
                    //因为i比j小,最次也是相等,所以可以不用二维辅助数组先去求和
                    //因为递增关系的存在,可以直接利用上一次的result[k]
                    result[k] = (i == j) ? d[i][k] : result[k] + d[j][k];
                    //因为计算一次就已经更新好了result[k],所以直接计算一维的最大子段和也不会受影响
                    if(temp >= 0)
                        temp += result[k];
                    else
                        temp = result[k];
                    //最后比较一下最大值
                    if(temp > maxSubMaxMartix)
                        maxSubMaxMartix = temp;
                }
            }
        }
        printf("%lld
    ",maxSubMaxMartix);
    }
    
    int main()
    {
        int i,j;
        scanf("%d%d",&M,&N);//N行M列
        for(i = 0; i < N; i++)
        {
            for(j = 0; j < M; j++)
            {
                scanf("%lld",&d[i][j]);
            }
        }
        getSubMaxMatrix();
    	return 0;
    }
    


    
    

  • 相关阅读:
    理财技术+人生感悟(转)
    程序员每天每月每年需要做的事(转)
    数据库常用函数(数字函数)
    数据库之常用函数 (日期函数)
    Qt初级-头文件
    Qt初级-成员函数(二)
    Qt初级-成员函数(一)
    Qt初级-Qt格式(二)
    Qt初级-Qt格式(一)
    Qt初级-Qt继承表
  • 原文地址:https://www.cnblogs.com/lemonbiscuit/p/7776100.html
Copyright © 2011-2022 走看看