初十hu测 T1.max(最大子矩阵启发)

这里写图片描述
这里写图片描述

分析:
先看一下正解:
这里写图片描述

然而我用了另一种方法:
枚举上下两行(确定了子矩阵的上下范围)
之后处理出每一列两个数的min值
以下讨论都基于这个min值(实际上就是把同一列上的两个数绑定了)

因为我们只关心是否存在,不关心子矩阵到底长什么样
(存在即合理)
因此对于一个min值X,只要存在比ta大元素,X就可以作为子矩阵的价值
我们只要找到这些min值之中的第二大即可

看似是一个 O(n3) O ( n 3 ) 的算法
然而我们可以加一点优化:预处理出每一行的最大值 mxi m x i
mxi m x i 小于当前得到的局部最优解
我们就没有必要枚举第i行了

tip

收到了最大子矩阵的启发
澍神说这是lrj的方法,蛮不错

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

const int INF=1e9;
int n,m,mp[1003][1003],mx[1003],ans;

int main()
{
    freopen("max.in","r",stdin);
    freopen("max.out","w",stdout);

    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) {
        mx[i]=-INF;
        for (int j=1;j<=m;j++) 
            scanf("%d",&mp[i][j]),mx[i]=max(mx[i],mp[i][j]);
    }

    ans=-INF;
    for (int i=1;i<n;i++) if (mx[i]>ans)
        for (int j=i+1;j<=n;j++) if (mx[j]>ans) {
            int max1=-INF,max2=-INF;
            for (int k=1;k<=m;k++) {
                int t=min(mp[i][k],mp[j][k]);
                if (t>max1) 
                    max2=max1,max1=t;
                else if (t<max1&&t>max2)
                    max2=t;
            }
            ans=max(ans,max2);
        }

    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值