1159 最大全0子矩阵

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
 
 
 
题目描述 Description

在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多。

输入描述 Input Description

输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开。

输出描述 Output Description

输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数。

样例输入 Sample Input

5
0 1 0 1 0
0 0 0 0 0
0 0 0 0 1
1 0 0 0 0
0 1 0 0 0

样例输出 Sample Output

9

https://wenku.baidu.com/view/cd82b3f5e87101f69f3195bc.html

/*
感觉很像“土豪聪要请客”,就用前缀和用同样的方法做了,结果超时
*/
#include<iostream>
#include<cstdio>
using namespace std;
int n,f[][],ans;
int main(){
//freopen("Cola.txt","r",stdin);
scanf("%d",&n);
int x;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
scanf("%d",&x);
f[i][j]=x^;
f[i][j]+=f[i][j-];
}
for(int i=;i<=n;i++){
for(int j=i;j<=n;j++){
int sum=,mx=;
for(int k=;k<=n;k++){
if(f[k][j]-f[k][i-]==(j-i+))sum++;
else sum=;
mx=max(mx,sum);
}
ans=max(ans,mx*(j-i+));
}
}
printf("%d",ans);
}

75分 前缀和TLE

学习材料:王知昆《浅谈用极大化思想解决最大子矩阵问题》
【最大子矩阵问题】
在一个给定的矩形中有一些障碍点,找出内部不包含障碍点的、轮廓与整个矩形平行或重合的最大子矩形。
【定义子矩形】
有效子矩形:内部不包含障碍点的、轮廓与整个矩形平行或重合的子矩形。
极大子矩形:每条边都不能向外扩展的有效子矩形。
最大子矩形:所有有效子矩形中最大的一个(或多个)。
【极大化思想】
在一个有障碍点的矩形中最大子矩形一定是极大子矩形。
设计算法的思路:枚举所有的极大子矩形,找到最大子矩形。
设NM分别为整个矩形的长和宽,S为内部的障碍点数。
【算法1】
时间复杂度:O(S^) 空间复杂度:O(S)
由于极大子矩形的每一条边都不能向外扩展,那么极大子矩阵的每条边要么覆盖了障碍点,要么与整个矩形的边界重合
基本算法:枚举上下左右四个边界,然后判断组成的矩形是否是有效子矩形。
复杂度:O(S^) 可以改进的地方:产生了大量的无效子矩形。
初步改进的算法:枚举左右边界,然后对处在边界内的点排序,每两个相邻的点和左右边界组成一个矩形。
复杂度:O(S^) 可以改进的地方:枚举了部分不是极大子矩形的情况。
综上,设计算法的方向:
、保证每一个枚举的矩形都是有效的。
、保证每一个枚举的矩形都是极大的。
算法的过程:
枚举极大子矩形的左边界——>根据确定的左边界,找出相关的极大子矩形——>检查和处理遗漏的情况
()按照横坐标从小到大的顺序将所有的点编号为1,,...
()首先选取1号点作为要枚举的极大子矩形的左边界,设定上下边界为矩形的上下边界
()从左到右扫描,第一次到2号点,确定一个极大子矩形,修改上下边界;第二次找到3号点,以此类推。
()将左边界移动到2号点,3号点,,,以同样的方法枚举
遗漏的情况:
、矩形的左边界与整个矩形的左边界重合。解决方法:用类似的方法从左到右扫一遍
、矩形的左边界与整个矩形的左边界重合,且矩形的右边界与整个矩形的右边界重合。解决方法:预处理时增加特殊判断。
优点:利用的极大化思想,复杂度可以接受,编程实现简单。
缺点:使用有一定的局限性,不适合障碍点较密集的情况。
【算法2】
时间复杂度O(NM) 空间复杂度O(NM)
定义
有效竖线:除了两个端点外,不覆盖任何一个障碍点的竖直线段。
悬线:上端覆盖了一个障碍点或者到达整个矩形上边界的有效线段。
每个悬线都与它底部的点一一对应,矩形中的每一个点(矩形顶部的点除外)都对应了一个悬线。
悬线的个数=(N-)*M;
如果把一个极大子矩形按照横坐标的不同切割成多个与y轴平行的线段,那么其中至少有一个悬线。
如果把一个悬线向左右两个方向尽可能的移动,那么就得到了一个矩形,我们称它为悬线对应的矩形。
悬线对应的矩形不一定是极大子矩形,因为下边界可能还可以向下扩展。
设计算法:
原理:所有悬线对应矩形的集合一定包含了极大子矩形的集合。
通过枚举所有的悬线,找出所有的极大子矩形。
算法规模:
悬线个数=(N-)×M
极大子矩形个数≤悬线个数
具体方法:
设 H[i,j]为点(i,j)对应的悬线的长度。
L[i,j]为点(i,j)对应的悬线向左最多能够移动到的位置。
R[i,j]为点(i,j)对应的悬线向右最多能够移动到的位置。 !考虑点(i,j)对应的悬线与点(i-,j)对应的悬线的关系(递推思想): 如果(i-,j)为障碍点,那么,如图所示,(i,j)对应的悬线长度1,左右能移动到的位置是整个矩形的左右边界。
即 H[i,j]=,
L[i,j]=,R[i,j]=m 如果(i-,j)不是障碍点,那么,如图所示,(i,j)对应的悬线长度为(i-,j)对应的悬线长度+。
即 H[i,j]=H[i-,j]+ •如果(i-,j)不是障碍点,那么,如图所示,(i,j)对应的悬线左右能移动的位置要在(i-,j)的基础上变化。
L[i-,j]
L[i,j]=max
(i-,j)左边第一个障碍点的位置
•同理,也可以得到R[i,j]的递推式
R[i-,j]
R[i,j]=min
(i-,j)右边第一个障碍点的位置 优点: 复杂度与障碍点个数没有直接关系。
缺点:障碍点少时处理较复杂,不如算法1。 代码实现具体见WC2002 奶牛浴场(算法1)
codevs1159最大全0子矩阵(算法2)

学习资料(悬线法)

#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 2010
int n,h[maxn],l[maxn],r[maxn];
int ans=,map[maxn][maxn];
int main(){
//freopen("Cola.txt","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&map[i][j]);
for(int i=;i<=n;i++)h[i]=,l[i]=,r[i]=n;
int ll,rr;
for(int i=;i<=n;i++){
ll=,rr=n+;
for(int j=;j<=n;j++){
if(map[i][j])h[j]=,l[j]=,ll=j;//遇到障碍
else h[j]++,l[j]=max(l[j],ll+);
}
for(int j=n;j>=;j--){
if(map[i][j])r[j]=n,rr=j;//遇到障碍
else r[j]=min(r[j],rr-),ans=max(ans,h[j]*(r[j]-l[j]+));
}
}
printf("%d",ans);
return ;
}

100分 悬线法

Codevs 1159 最大全0子矩阵的更多相关文章

  1. Codevs 1159 最大全0子矩阵 悬线法!!!!

    1159 最大全0子矩阵 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O ...

  2. CODE[VS] 1159 最大全0子矩阵

    写一道CODEVS的题目 其实我还是很喜欢CODEVS的界面的 主要是系统地学习一下悬线法这个看似十分简单,实际就是十分简单的算法 对于一些详细的东西参考dalao's blog,不喜勿喷 对于悬线法 ...

  3. [codevs1159]最大全0子矩阵(悬线法)

    解题关键:悬线法模板题.注意此模板用到了滚动数组. #include<cstdio> #include<cstring> #include<algorithm> # ...

  4. 【DP/单调栈】关于单调栈的一些题目(codevs 1159,codevs 2673)

    CODEVS 2673:Special Judge 题目描述 Description   这个月的pku月赛某陈没有参加,因为当时学校在考试[某陈经常逃课,但某陈还没有强大到考试也可以逃掉的程度].何 ...

  5. poj3494Largest Submatrix of All 1’s(最大全1子矩阵)

    题目链接:http://poj.org/problem?id=3494 题目大意: 出1个M*N的矩阵M1,里面的元素只有0或1,找出M1的一个子矩阵M2,M2中的元素只有1,并且M2的面积是最大的. ...

  6. POJ 3494 Largest Submatrix of All 1’s(最大全1子矩阵)

    题目链接:http://poj.org/problem?id=3494 题意:给出一个01的矩阵,找出一个面积最大的全1矩阵. 思路:用h[i][j]表示从位置(i,j)向上连续1的最大长度.之后枚举 ...

  7. [NOIP复习]第三章:动态规划

    一.背包问题 最基础的一类动规问题.相似之处在于给n个物品或无穷多物品或不同种类的物品,每种物品仅仅有一个或若干个,给一个背包装入这些物品,要求在不超出背包容量的范围内,使得获得的价值或占用体积尽可能 ...

  8. BZOJ 1057 棋盘制作(最大01相间子矩阵)

    求最大01相间子矩阵可以转换为求最大全0子矩阵.只需把棋盘(x+y)为奇数的取反,而该问题可以用经典的悬线法O(n^2)的求解. 悬线法呢. 首先定义b[i][j],为a[i][j]向上的最大连续0的 ...

  9. BZOJ1057 [ZJOI2007]棋盘制作

    Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应 ...

随机推荐

  1. UER#7 T2

    题意:给定n个数,对于2到n,分别输出一个答案.答案定义为:对于当前的数k,在原数组中找一个长度为k的区间,使得区间最值之差最小,输出差值.注意,差值允许5%的误差. 很少看见近似算法的题啊..跪烂V ...

  2. Linux学习之路(四)帮助命令

    帮助命令man .man 命令 #获取指定命令的帮助 .man ls #查看ls的帮助 man的级别 1 查看命令的帮助 2 查看可被内核调用的函数的帮助 3 查看函数的函数库的帮助 4 查看特殊文件 ...

  3. 2017SN多校D1T1 loveletter:模拟

    题意: 两张n*m的纸.一张透明纸,上面有些地方是黑的,有些地方是透明的.另一张纸上写满了字母. 你需要将透明纸放在写字的纸上,分别顺时针旋转0°.90°.180°.270°,每次从上到下.从左到右写 ...

  4. layer 插件 在子页面关闭自身的方法

    先取到该子页面在父级页面中的name 值 var  index= parent.layer.getFrameIndex(Window.name); 然后用该方法关闭 parent.layer.clos ...

  5. python 3 - 写一个注册的程序,账号和密码都存在文件里面

    choice = input('请输入你的选择:1,注册2.删除用户3.登录') #注册 输入 账号 密码 密码确认 # #需要校验用户是否存在,两次输入的密码,是否一致,为空的情况 #账号和密码都存 ...

  6. BZOJ-3626:LCA(离线+树链剖分)

    Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...

  7. ACM学习历程——POJ3468 A Simple Problem with Integers(线段树)

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  8. element el-input 自动获取焦点和IE下光标位置解决方法

    在实际开发中我们经常会碰到这样的场景,就是有input的地方都喜欢切换过去input自动获取焦点. 如果这个问题是在input中,很容易就实现了,但是element里面的el-input看源码,其实不 ...

  9. Mesos的quorum配置引发的问题

    Mesos安装完毕后,发现agent无法和master关联(通过WebUI的agent页面无法看到agent信息),查看日志显示: Elected as the leading master! sta ...

  10. AtCoder Grand Contest 002 F:Leftmost Ball

    题目传送门:https://agc002.contest.atcoder.jp/tasks/agc002_f 题目翻译 你有\(n*k\)个球,这些球一共有\(n\)种颜色,每种颜色有\(k\)个,然 ...