2021“MINIEYE杯”中国大学生算法设计超级联赛(1)1008 Maximal submatrix
2021/7/28 14:35:51
本文主要是介绍2021“MINIEYE杯”中国大学生算法设计超级联赛(1)1008 Maximal submatrix,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
https://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1008&cid=984
题意:
从n行m列矩阵中,找出最大的满足每列不降的子矩阵
题解:
如果下一列比上一列的数大,标记T,否则标记F
问题转化为在n-1行m列矩阵中,找最大的T子矩阵
可以用悬线法,也可以单调栈
单调栈法:
枚举每一行作为子矩阵的下边界,用一个数组记录到当前行时,每一列向上连续的T数量
即遇到T加1,遇到F清零
然后用2次单调栈分别计算以每一列为T矩阵高度,向左向右能延长的宽度
因为假设若这一列往上有连续x个T,那么他只能延伸到至少有x个T的列
这个可以维护单调递增的栈求
#include<bits/stdc++.h> using namespace std; #define N 2001 int m; int a[N][N]; char b[N][N]; int c1[N],c2[N]; int q[N],t[N]; int l[N],r[N],tmp[N]; void sol(int *c,int *p) { // for(int i=1;i<=m;++i) printf("%d ",c[i]); // printf("\n"); int top=0,last=0; for(int i=1;i<=m;++i) { if(!c[i]) { top=0; last=i; continue; } while(top && c[i]<=q[top]) --top; if(top) p[i]=t[top]+1; else p[i]=last+1; q[++top]=c[i]; t[top]=i; } } int main() { int T,n,ans; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { scanf("%d",&a[i][j]); if(a[i][j]>=a[i-1][j]) b[i-1][j]='T'; else b[i-1][j]='F'; } for(int i=1;i<=m;++i) c1[i]=c2[i]=0; ans=m; for(int i=1;i<n;++i) { for(int j=1;j<=m;++j) if(b[i][j]=='T') { c1[j]++; c2[m-j+1]++; } else { c1[j]=0; c2[m-j+1]=0; } sol(c1,l); sol(c2,r); for(int j=1;j<=m;++j) tmp[j]=r[j]; for(int j=1;j<=m;++j) r[j]=m-tmp[m-j+1]+1; for(int j=1;j<=m;++j) if(c1[j]) ans=max(ans,(c1[j]+1)*(r[j]-l[j]+1)); } printf("%d\n",ans); } }
这篇关于2021“MINIEYE杯”中国大学生算法设计超级联赛(1)1008 Maximal submatrix的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-20RabbitMQ教程:新手入门指南
- 2024-11-20Redis教程:新手入门指南
- 2024-11-20SaToken教程:新手入门指南
- 2024-11-20SpringBoot教程:从入门到实践
- 2024-11-20Java全栈教程:从入门到实战
- 2024-11-20Java微服务系统教程:入门与实践指南
- 2024-11-20Less教程:初学者快速上手指南
- 2024-11-20MyBatis教程:新手快速入门指南
- 2024-11-20QLExpress教程:初学者快速入门指南
- 2024-11-20订单系统教程:从入门到实践的全面指南