POJ 3494 Largest Submatrix of All 1’s

Description

Given a m-by-n (0,1)-matrix, of all its submatrices of all 1’s which is the largest? By largest we mean that the submatrix has the most elements.

Input

The input contains multiple test cases. Each test case begins with m and n (1 ≤ m, n ≤ 2000) on line. Then come the elements of a (0,1)-matrix in row-major order on m lines each with n numbers. The input ends once EOF is met.

Output

For each test case, output one line containing the number of elements of the largest submatrix of all 1’s. If the given matrix is of all 0’s, output 0.

Sample Input

2 2
0 0
0 0
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0

Sample Output

0
4 释意:
  给出一个由0,1组合的矩阵,试求出元素最多且都是1的矩形。 poj2559加强版。
题解:
1.将矩阵看成不同高度矩形,若相邻两行中若有1相邻则次矩形的高度便加1,将每一行分别看做矩形的底进行更新,从而问题变成了找面积最大矩形
举例说明:
因为我们要找的是矩形,所以它一定是以 某个行元素开始的,如果枚举行的时候,我们会发现:
对于第一行: 

对于第二行:

第三行:

第四行: 

这样的话,其实我们要找到的某个矩形就转换成 一某一个行开始的 histogram的最大矩形问题了。

那么我们原始矩形可以变成如下的形式的数据:

第一行表示,我们以第一行作为底边,所形成的矩形的高度,其他行也类似。

2.求以第i行为底的最大矩形,利用单调队列或者单调栈,以单调队列为例:

对该行中的每个点的高度为最小基准向左右两边进行松弛,求其可满足的左右区间的最大区间。

以右区间为例:

从该行的右端点开始一次进队遍历,建立单调增的队列将队尾与当前点的高度进行比较,若大于等于,则队尾出队,否则队尾元素的下标便是以当前点高度为最小高度的矩形的右区间最大值+1.

左区间同理亦可得到,从而确定该点所决定的矩形的大小,进而却定以该行为底的最大矩形。

3.代码实现:

 //单调队列实现  C++提交 若用G++则会T!!!!!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include<string.h>
#include<stack>
#include<set>
#include <queue>
using namespace std;
struct Node
{
int val;
int position;
}q[]; // 数组模拟单调递增队列
int n,m;
int l[]; // 以当前点高度为最小高度的矩形的左区间最大值
int r[]; //以当前点高度为最小高度的矩形的右区间最大值
int a[][];
//求每一行的最大矩形
int AREA(int nn)
{
int h = ; //队头
int tail = ;//队尾
//确定以每一个点的高度为最小值的矩形的右区间的最大值
q[].position = n+;
q[].val = -;
for(int i = m;i>=;i--)
{
while(q[tail].val >= a[nn][i]) tail--;
r[i] = q[tail].position-i;
q[++tail].val = a[nn][i];
q[tail].position = i;
}
//确定以每一个点的高度为最小值的矩形的左区间的最大值
h = ;
tail = ;
q[].position = ;
q[].val = -;
for(int i = ;i<=m;i++)
{
while(q[tail].val>=a[nn][i]) tail--;
l[i] = i-q[tail].position;
q[++tail].val = a[nn][i];
q[tail].position = i;
}
//该行中所有矩形的最大值
int max1 = -;
for(int i = ;i<=m;i++)
max1 = max(max1,(l[i]+r[i]-)*a[nn][i]);
return max1;
}
int main()
{ while(~scanf("%d %d",&n,&m))
{
for(int i = ;i<=n;i++)
for(int j = ;j<=m;j++)
scanf("%d",&a[i][j]);
//讲矩阵看做不同高度的矩形进行更新操作
for(int i = ;i<=n;i++)
for(int j = ;j<=m;j++)
if(a[i][j]) a[i][j] = a[i-][j]+a[i][j];
int max1 = -;
//对每行进行遍历确定每行的最大矩形
for(int i = ;i<=n;i++)
max1 = max(AREA(i),max1);
printf("%d\n",max1);
}
return ;
}
 //单调栈实现
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include<string.h>
#include<stack>
#include<set>
#include <queue> using namespace std;
struct re
{
int h;
int p;
}; int m,n;
int a[][];
int h[][];
int l[];
int r[];
int AREA(int R)
{
int i,j;
int max1 = -;
stack<re> s;
//求左区间
re p0,pi;
p0.h = -;
p0.p = -;
s.push(p0);
for(i = ;i<n;i++)
{
pi.p = i;
pi.h = h[R][i];
while(s.top().h>=pi.h) s.pop();
l[i] = i-s.top().p;
s.push(pi);
}
while(!s.empty()) s.pop();
//求右区间
p0.h = -;
p0.p = n;
s.push(p0);
for(i =n- ;i>=;i--)
{
pi.p = i;
pi.h = h[R][i];
while(s.top().h>=pi.h) s.pop();
r[i] = s.top().p-i;
s.push(pi);
}
for(i = ;i<n-;i++)
if((r[i]+l[i]-)*h[R][i]>max1)
max1= (r[i]+l[i]-)*h[R][i];
return max1;
}
int main()
{
int i,j;
while(~scanf("%d%d",&m,&n))
{
for(i = ; i<m; i++)
for(j = ; j<n; j++)
{
scanf("%d",&a[i][j]);
h[i][j] = a[i][j];
}
for(i = ; i<n; i++)
for(j = ; j<m; j++)
if(h[j][i]) h[j][i] += h[j-][i];
int max1 = -;
for(i = ; i<m; i++) max1 = max(max1,AREA(i));
printf("%d\n",max1);
}
}
本文为个人随笔,如有不当之处,望各位大佬多多指教.
若能为各位博友提供小小帮助,不胜荣幸.

最新文章

  1. 【Python】用户登录三次锁定
  2. 第一篇博文,整理一下关于Mac下安装本地LNMP环境的一些坑
  3. [非原创]Project facet Java version 1.8 is not supported解决记录
  4. push submodule
  5. 改变Vim在iTerm2中的光标
  6. BurpSuite抓App数据包的方法
  7. XStream xml转java对象
  8. BluetoothAdapter.LeScanCallback 参考文档
  9. python 安装 memcache
  10. jar2exe 配置jre
  11. Appium适配Android7.0以上版本
  12. rpm检验是否被改动过
  13. 【Halum操作-UVA 11478】
  14. h5 canvas与SVG的比较
  15. mysql使用druid监控配置
  16. 基础SELECT实例
  17. IntelliJ IDEA 2017版 SpringBoot的核心配置详解
  18. Java编程中获取键盘输入实现方法及注意事项
  19. 关于finecms v5 会员头像 任意文件上传漏洞分析
  20. Python tan() 函数

热门文章

  1. js 生成随机数解决缓存的问题
  2. UVA Live Achrive 4327 Parade (单调队列,dp)
  3. vuejs组件
  4. BZOJ 2502: 清理雪道
  5. 2017.12.13 Java中是怎样通过类名,创建一个这个类的数组
  6. android设备局域网中快速搜索之cling方式
  7. 【Java】基本数据类型以及其转换
  8. linux的一些指令
  9. c++ 中十进制 八进制 十六进制 二进制转换 最简方法
  10. Linux问题分析或解决_samba无法连接