枚举技巧——积分图

枚举技巧——积分图

很多时候,我们会处理矩阵上问题,大部分都是寻找一个可行最优子矩形区域。如果枚举两个顶点时间复杂度为 O ( ( N M ) 2 ) O((NM)^2) O((NM)2)。下面介绍一种积分图的方式。

积分图

我们枚举上下两个边界,将边界围成的矩形压成一个数组,至于同列的数据怎么合并,还要看题目的具体要求。

之后,我们面对的就是一个一维问题了,相对来说,同等的一维问题更好解决,一般是使用DP求解。

这样一来,时间复杂度就是 O ( N 2 M ) O(N^2M) O(N2M)。时间复杂度降低了一个等级。

如果列数比较少,行数比较多,我们还可以合并列。

例题

LeetCode 363

class Solution
{
public:
    int psum[105][105];
    void buildPsum(vector<vector<int>> &matrix)
    {
        for (int r = 1; r <= matrix.size(); r++)
            for (int c = 1; c <= matrix[0].size(); c++)
            {
                psum[r][c] = psum[r][c - 1] + psum[r - 1][c] - psum[r - 1][c - 1] + matrix[r - 1][c - 1];
            }
    }

    int getSum(int r1, int r2, int c)
    {
        return psum[r2 + 1][c + 1] - psum[r1][c + 1] - psum[r2 + 1][c] + psum[r1][c];
    }

    int solve(int r1, int r2, int cm, int k)
    {
        set<int> st;
        int ppsum = 0;
        int ans = INT_MIN;
        st.insert(0);
        for (int i = 0; i < cm; i++)
        {
            ppsum += getSum(r1, r2, i);

            auto it = st.lower_bound(ppsum - k);

            if (it != st.end())
            {
                ans = max(ans, ppsum - *it);
            }

            st.insert(ppsum);
        }
        return ans;
    }

    int maxSumSubmatrix(vector<vector<int>> &matrix, int k)
    {
        buildPsum(matrix);

        // 枚举行
        int ans = INT_MIN;
        for (int r1 = 0; r1 < matrix.size(); r1++)
        {
            for (int r2 = r1; r2 < matrix.size(); r2++)
            {
                ans = max(ans, solve(r1, r2, matrix[0].size(), k));
            }
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值