最大子矩阵问题(dp)

@(E ACMer)


    题意:给你一个矩阵,求它的所有元素和最大的子矩阵.
    分析:

    我们只知道一维的情况就是经典的最大子段和.然而维数达到二维就变的复杂了.
    我们观察数据范围500,易想到 n3 的算法也能过.纯暴力是 n4 的方法
    然后可以通过枚举其中一维,dp最后一维的方法求出.
    处理列上的和为前缀和,然后枚举列的开头和结尾,形成的段,然后再在行上进行最大子段和复杂度刚好 n3

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <set>
    #include <map>
    #include <stack>
    #include <vector>
    #include <string>
    #include <queue>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    using namespace std;
    typedef pair<int, int> pii;
    typedef long long ull;
    typedef long long ll;
    typedef vector<int> vi;
    #define xx first
    #define yy second
    #define rep(i, a, n) for (int i = a; i < n; i++)
    #define sa(n) scanf("%d", &(n))
    #define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)
    const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;
    
    ll a[555][555];
    ll dp[555];
    
    int main(void) {
    #ifdef LOCALs
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
        int T;
        cin >> T;
        while (T--) {
            int n, m;
            sa(n), sa(m);
            memset(a, 0, sizeof(a));
            memset(dp,0,sizeof (dp));
                    for(int i = 1; i<=n; i++)
                    {
                        for(int j=1; j<=m; j++)
                        {
                            scanf("%lld",&a[i][j]);
                            a[i][j] += a[i-1][j];
                        }
                    }
    
                    ll max_sum=-INF;
                    for(int i=1; i<=n; i++)
                    {
                        for(int j= 0; j < i; j++)
                        {
                            for(int k=1; k<=m; k++)
                            {
                                dp[k] = a[i][k]-a[j][k];
                                dp[k] = max(dp[k], dp[k] + dp[k - 1]);
                                if(dp[k]>max_sum)  
                                    max_sum=dp[k];  
                            }  
                        }  
                    }  
                    printf("%lld\n",max_sum);
    
        }
        return 0;
    }
    
    
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值