题目描述:

在一个M * N的矩阵中,所有的元素只有0和1,从这个矩阵中找出一个面积最大的全1子矩阵,所谓最大是指元素1的个数最多。

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行是两个整数m、n(1<=m、n<=1000):代表将要输入的矩阵的大小。
矩阵共有m行,每行有n个整数,分别是0或1,相邻两数之间严格用一个空格隔开。

输出:

对应每个测试案例,输出矩阵中面积最大的全1子矩阵的元素个数。

样例输入:
2 2
0 0
0 0
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
样例输出:0 4

解题思路:转载自http://www.cnblogs.com/fstang/archive/2013/05/19/3087746.html

方法是:

1、先将0/1矩阵读入x,对每一个非零元素x[i][j],将其更新为:在本行,它前面的连续的1的个数+1(+1表示算入自身)

  比如,若某一行为0 1 1 0 1 1 1,则更新为0 1 2 0 1 2 3

2、对每一个非零元素x[i][j],在第j列向上和向下扫描,直到遇到比自身小的数,若扫描了y行,则得到一个大小为x[i][j]*(y+1)的全1子矩阵(+1表示算入自身所在行)

  比如,若某一列为[0 3 4 3 5 2 1]'(方便起见,这里将列表示成一个列向量),我们处理这一列的第4个元素,也就是3,它向上可以扫描2个元素,向下可以扫描1个元素,于是得到一个4×3的全1子矩阵。

3、在这些数值中取一个最大的。

思想大概如下图所示(空白处的0没有标出)

对照步骤2中给出的例子,蓝色的箭头表示向上向下扫描,黑色的框表示最终得到的全1子矩阵

这样做为什么是对的?

想一想,对那个最大的全1子矩阵,用这种方法能不能找到它呢?——肯定可以。

一个最大全1子矩阵,肯定是四个边界中的每一个都不能再扩展了,如下图

假设图中全1子矩阵就是最大子矩阵,则左边界左侧那一列肯定有一个或多个0(否则就可以向左边扩展一列,得到一个更大的全1矩阵)

对其他3个边界有类似的情况。

然后看图中用黑圈标出的1(其特点是:和左边界左侧的某个0在同一行),从这个1出发,按照之前的方法,向上向下扫描,就可以得到这个子矩阵。所以,肯定可以找到。

下面是我的代码,实际实现的时候,为了提高效率,估计了一下upperbound,这个upperbound就是:在当前列,

包含x[i][col]的连续的非零序列的和,比如对某列[0 3 4 3 5 2 1]',后面6个的upperbound都是
3 + 4 + 3 + 5 + 2 + 1 = 18,对于0元素,不需要upperbound

 #include<iostream>
using namespace std; int main()
{
int n,m;
while(cin>>n>>m){
int **array=new int*[n];
int **upperbound=new int*[n];
for(int i=;i<n;i++){
array[i]=new int[m];
upperbound[i]=new int[m];
for(int j=;j<m;j++){
cin>>array[i][j];
upperbound[i][j]=;
}
}
//prepare:
for(int i=;i<n;i++){
for(int j=;j<m;j++){
if(array[i][j]==&&array[i][j-]!=)array[i][j]=array[i][j-]+;
}
}
//计算upperbound
for(int j=;j<m;j++){
for(int i=;i<n;i++){
if(array[i][j]==)continue;
else{
int sum=,temp=i;
while(temp<n&&array[temp][j]>){
sum+=array[temp][j];
temp++;
}
for(int k=i;k<temp;k++){
upperbound[k][j]=sum;
}
i=temp;
}
}
} int maxarea=;
for(int i=;i<n;i++){
for(int j=;j<m;j++){
if(array[i][j]!=&&maxarea<upperbound[i][j]){
int cnt=,val=array[i][j];
for(int row=i-;row>;row--){
if(array[row][j]>=val)cnt++;
else
break;//这里一定要break
}
for(int row=i+;row<n;row++){
if(array[row][j]>=val)cnt++;
else
break;//这里一定要break
}
if(cnt*val>maxarea)maxarea=cnt*val;
}
}
}
cout<<maxarea;
}
return ; }

面积最大的全1子矩阵--九度OJ 1497的更多相关文章

  1. 九度OJ 1497 面积最大的全1子矩阵 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1497 题目描述: 在一个M * N的矩阵中,所有的元素只有0和1,从这个矩阵中找出一个面积最大的全1子矩阵,所谓最 ...

  2. [Jobdu] 题目1497:面积最大的全1子矩阵

    题目描述: 在一个M * N的矩阵中,所有的元素只有0和1,从这个矩阵中找出一个面积最大的全1子矩阵,所谓最大是指元素1的个数最多. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行是 ...

  3. 九度oj题目&amp;吉大考研11年机试题全解

    九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码).    http://ac.jobdu.com/problem.php?pid=11 ...

  4. 九度oj 题目1087:约数的个数

    题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...

  5. 九度OJ 1502 最大值最小化(JAVA)

    题目1502:最大值最小化(二分答案) 九度OJ Java import java.util.Scanner; public class Main { public static int max(in ...

  6. 九度OJ,题目1089:数字反转

    题目描述: 12翻一下是21,34翻一下是43,12+34是46,46翻一下是64,现在又任意两个正整数,问他们两个数反转的和是否等于两个数的和的反转. 输入: 第一行一个正整数表示测试数据的个数n. ...

  7. 九度OJ 1500 出操队形 -- 动态规划(最长上升子序列)

    题目地址:http://ac.jobdu.com/problem.php?pid=1500 题目描述: 在读高中的时候,每天早上学校都要组织全校的师生进行跑步来锻炼身体,每当出操令吹响时,大家就开始往 ...

  8. 九度OJ 1531 货币面值(网易游戏2013年校园招聘笔试题) -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1531 题目描述: 小虎是游戏中的一个国王,在他管理的国家中发行了很多不同面额的纸币,用这些纸币进行任意的组合可以在 ...

  9. 九度OJ 1024 畅通工程 -- 并查集、贪心算法(最小生成树)

    题目地址:http://ac.jobdu.com/problem.php?pid=1024 题目描述:     省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但 ...

随机推荐

  1. 爬虫Larbin解析(二)——sequencer()

    分析的函数: void sequencer() //位置:larbin-2.6.3/src/fetch/sequencer.ccvoid sequencer() { bool testPriority ...

  2. git使用(一)

    github因为众所周知的一些问题,不方便选为远程仓库,在此,我们选用oschina的远程仓库,首先去http://git.oschina.net/申请一个账号. 第一步,安装git(下载电脑系统对应 ...

  3. LINUX内核分析第四周学习总结——扒开应用系统的三层皮(上)【转】

    转自:http://www.cnblogs.com/lalacindy/p/5276874.html 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://moo ...

  4. js动态判断密码强度&&实用的 jQuery 代码片段

    // 网上拷贝的代码,效果不太好需要自己调整<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q ...

  5. [分享] VIM 常用命令及游戏练级

    分享一个不错的文章,讲解了 VIM 的常用命令. http://coolshell.cn/articles/5426.html 另,介绍一个可以帮助熟悉VIM命令的练级游戏. 游戏地址:http:// ...

  6. ubuntu 14.04 与 CentOS 升级GCC/G++至5版本

    # 支持 ubuntu 14.04 add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update apt-get i ...

  7. hdu - 1240 Nightmare && hdu - 1253 胜利大逃亡(bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=1240 开始没仔细看题,看懂了发现就是一个裸的bfs,注意坐标是三维的,然后每次可以扩展出6个方向. 第一维代表在 ...

  8. C#图片压缩的实现方法

    一般在web应用中,对客户端提交上来的图片肯定需要进行压缩的.尤其是比较大的图片,如果不经过压缩会导致页面变的很大,打开速度比较慢,当然了如果是需要高质量的图片也得需要生产缩略图. 一般在web应用中 ...

  9. 启用ntp服务

    1. 主服务器 修改配置vi /etc/ntp.conf restrict 192.168.2.0 mask 255.255.255.0 nomodify notrap #允许别的服务器同步 serv ...

  10. 内存分配(c/c++)

    C++中内存分配          内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 1,栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区.里面的 ...