NOI:最大子矩阵

一、题目大意

在这里插入图片描述

二、解题思想

1、TE: 利用sum[i][j]记录(i,j)左上方所有的和,然后利用前缀和的思想快速求出某个矩阵的和。最后使用四重循环,但是超时。
2、AC: 使用压缩维度和动态规划思想。
(1)压缩维度

  • 定义 s u m O f L i n e [ i ] [ j ] sumOfLine[i][j] sumOfLine[i][j]:为第 j j j列上前 i i i行所有数的和。使用 O ( n 2 ) O(n^2) O(n2)求出结果。

(2)动态规划:

  • 最大子矩阵必定横跨某两行。
  • 对任意一个横跨 [ i , j ] [i,j] [i,j]行的矩阵,我们使用 s u m O f L i n e sumOfLine sumOfLine快速将其压缩为一维,然后求这个一维数组的最大连续子序列和。
  • 任意两行组合的最大值即为最终答案。
  • O ( n 3 ) O(n^3) O(n3)

三、代码

#include<iostream>
#include<stdio.h>
using namespace std;
const int MAX = 105;
const int inf = 1 << 30;
int grad[MAX][MAX];
int sum_of_line[MAX][MAX];
int line[MAX];
int get_max_sequence(int n)
{
    int dp[MAX];
    dp[1] = line[1];
    for(int i=2; i<=n; i++)
        dp[i] = max(line[i], dp[i-1]+line[i]);
    int res = -inf;
    for(int i=1; i<=n; i++)
        res = max(dp[i], res);
    return res;
}
int main()
{
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            scanf("%d", &grad[i][j]);
    // ---------------计算行前缀和-----------------------------
    for(int j=1; j<=n; j++)
        for(int i=1; i<=n; i++)
            sum_of_line[i][j] = sum_of_line[i-1][j] + grad[i][j];
	// --------------------------------------------------------------
    int ans = -inf;
    for(int r1=1; r1<=n; r1++)
    {
        for(int r2=r1; r2<=n; r2++)
        {
            for(int j=1; j<=n; j++)
                line[j] = sum_of_line[r2][j] - sum_of_line[r1-1][j];

            int line_max = get_max_sequence(n);
            ans = max(line_max, ans);
        }
    }
    cout << ans << endl;
    return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值