TYVJ 最美妙的矩阵

背景 Background
Candy的生日即将到来,飘飘乎居士希望找到一个最美妙的矩阵送个Candy作为礼物
描述 Description
飘飘乎居士从Pink处得知最美妙的矩阵满足三个条件:首先,它的长和宽都必须和矩阵的边界平行(也就是不可以出现斜的矩阵);第二:子矩阵横竖都要满足单调递增(可以相等,也就是对于每一个最优子矩阵的元素都要满足a[i][j]>=a[i-1][j] and a[i][j]>=a[i][j-1],其中a[i][j]表示矩阵第i行第j列的数字);第三:最优矩阵是在满足上述两个条件中面积最大的矩阵。
输入格式 InputFormat
第一行,两个正整数n,m
        接下来n行,每行m个数字,构成一个n*m的矩阵

输出格式 OutputFormat
一行,代表最优矩阵的面积
样例输入 SampleInput 
3 4
2 4 4 4
4 4 4 2
3 4 2 5
样例输出 SampleOutput 
6
数据范围和注释 Hint
最优子矩阵为
     2 4 4
     4 4 4
     该矩阵满足横竖都单调递增,并且是所有满足条件中面积最大的。其中矩阵长为3宽为2,面积为6,也就是最后的答案。
对于30%的数据  0<n m<=50
对于100%的数据 0<n m<=200
对于所有数据 a[i][j]<=20000000

题解

时间及空间复杂度题解
时间复杂度:O(n^6)

空间复杂度:O(n^2)

方法一:枚举子矩阵的每一个左上角坐标和右下角坐标,在逐个检查枚举的矩阵是否符合单调特性。预期得分30
时间复杂度:O(N^3)

空间复杂度:O(N^3)

方法二:预处理column[i][j]以及can[i][j][k]数组。

 

其中column[i][j]表示坐标为i j的点能向上单调递减的长度。则

column[i][j]={column[i-1][j]+1(a[i][j]>=a[i-1][j]),column[i][j]=1}

 

用can[i][j][k]表示从第i行到第j行中的第k列能否接道第i行到第j行的k-1列中,则关于can[i][j][k]=true的条件为

(can[i][j-1][k])and(column[j][k]>=j-i+1)and(a[j][k]>=a[j][k-1])and(coulumn[j][k-1]>=j-i+1。

 

接下来用f[i][j][k]表示从第i行到第j行中,第k列的最大子矩阵

F[i][j][k]=f[i][j][k-1]+j-i+1   (can[i][j][k]=true)

=j-i+1 (can[i][j][k]=false and column[j][k]>=j-i+1)

=0 (else)

预期得分100


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
int n,m,a[201][201],u[201][201],f[201][201][201],ans;
bool can[201][201][201];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
          scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
       {if(a[i][j]>=a[i-1][j])u[i][j]=u[i-1][j]+1;
        else u[i][j]=1;
	   }
    for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
    for(int k=1;k<=m;k++)
	   {if((can[i][j-1][k]||j-1<i)&&u[j][k]>=j-i+1&&a[j][k]>=a[j][k-1]&&u[j][k]>=j-i+1)
           can[i][j][k]=1;
	   }
    for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
    for(int k=1;k<=m;k++)
       {if(can[i][j][k]) f[i][j][k]=f[i][j][k-1]+j-i+1;
        else if(u[j][k]>=j-i+1) f[i][j][k]=j-i+1;
        ans=max(ans,f[i][j][k]);
       }
    printf("%d",ans);
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值