2017衢州联赛第三题题解

来源:互联网 发布:ubuntu开启3306端口 编辑:程序博客网 时间:2024/05/02 04:28

最大矩阵

(matrix.pas/c/cpp)

【问题描述】
在看过萝卜同学的游戏后, Fbs 表示太无趣了。他想试试萝卜同学能不能玩点级别更高的游戏,于
是他想了个难度大点的。
首先他定义:一个矩阵的权值为这个矩阵四个角上的数值的最小值。现在 Fbs 给出一个 N*M 的矩阵,
以及矩阵上的数值, 他想让萝卜同学在这个矩阵中寻找到一个权值最大的子矩阵。萝卜同学看了一眼就
傻眼了,表示他不能玩这游戏,但是他很机灵,偷偷的向你求助, 所以请你告诉他这个最大权值。
【输入格式】
第一行两个数 N,M
接下来一个 N*M 的矩阵
【输出格式】
一个数表示最大权值
【样例输入】
3 3
1 0 1
0 1 0
0 1 1
【样例输出】
0
【样例解释】
可以发现无论选择哪个子矩阵四角都至少有一个 0。
【数据说明】
对于 10%的数据: 1<=N,M<=50
对于 30%的数据: 1<=N,M<=200
对于 100%的数据: 1<=N,M<=2000, 所有的数值不超过 10^9
【限制】
时间:1.5s 空间:256MB;

【题目分析】

考场上我只写出了O(n^3)的方法,每次枚举两列,然后一行一行的刷,二分我是有想过,就是不知道check怎么写,后来我看了题解,嗯……我果然是个JR(蒟蒻)。
首先这道题很容易想到二分枚举答案,然后进行check,开一个数组c,枚举行,先将这行中比答案大的全加入数组,然后接下来都O(n^2)两两枚举,定义布尔数组g[i][j],表示前面第i个元素和第j个元素是否在同一行大于答案,如果这次枚举发现g[i][j]为真,那么说明这一行和前面某一行都有i和j大于答案,那么这个矩阵四个角全大于矩阵,查找成功,退出,否则为了下次的枚举,g[i][j]赋值给1。
最后吐槽一下本地评测的时候所有考试评测AC的代码都TLE了,包括本JR的订正代码,后来在网上找到了一个神奇的读优,然后……就过了……

【复杂度】
时间:O(n^3*log(max_a[i])); (当然实际会比这小的多);
空间:O(n^2);

#include<cstdio>#include<cstring>using namespace std;int n,m,ans,L,R,a[2005][2005],c[2005];bool f[2005][2005];inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void readi(int &sum){    char ch=nc(); sum=0;    while(!(ch>='0'&&ch<='9'))ch=nc();    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();}bool _check(int x){    memset(f,0,sizeof(f));    for (int i=1;i<=n;i++)    {        int q=0;        for (int j=1;j<=m;j++) if (a[i][j]>=x) c[++q]=j;        for (int j=1;j<q;j++)          for (int k=j+1;k<=q;k++)            if (f[c[j]][c[k]]) return true; else f[c[j]][c[k]]=1;    }    return false;}int main(){    freopen("matrix.in","r",stdin);    freopen("matrix.out","w",stdout);    readi(n); readi(m); ans=0;    for (int i=1;i<=n;i++)      for (int j=1;j<=m;j++){        readi(a[i][j]);        if (L>a[i][j]) L=a[i][j];        if (R<a[i][j]) R=a[i][j];      }    while (L<=R)    {        int mid=((R-L)>>1)+L;        if (_check(mid)){            ans=mid; L=mid+1;        }        else R=mid-1;    }    printf("%d",ans);    return 0;}

PS:
关于读优:
读入优化新姿势——学习笔记 http://blog.csdn.net/chhnz/article/details/72672962
震惊!99.999%的OIER都不知道!我竟然学了假读优!竟然有这样的读优!
http://blog.csdn.net/FYOIER/article/details/72667544

在此对以上两位作者兼大牛ZH大佬和FY大佬表示崇敬和Orz
Orz ZH Orz FY

原创粉丝点击