码迷,mamicode.com
首页 > 其他好文 > 详细

重(zhong)新学习悬线法

时间:2017-09-29 00:15:11      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:表示   系统   最大子矩阵   经典   能力   int   ++   左右   转移   

2017.9.28今天模拟赛T1就是求最大子矩阵的经典题

然而我已经好久没有写悬线了,以前悬线也是拉的,于是现在就系统的学习一波吧

给定一个N * M的01矩阵,求最大全0矩阵的大小

N^3的做法其实有很多种,前缀和乱搞什么的都可以

考虑N^2的做法

对于任意一个非1的点i,j,记其向上能到达的最长长度为up[i][j]

显然up[i][j] = up[i-1][j] + 1 (a[i][j] == 0)

up[i][j] = 0 (a[i][j] = 1)我们称up[i][j]为一条悬线

显然必然存在一段区间L,R满足 L<=j<=R使得1-i行中 L,R之间所有悬线都>= up[i][j]

令L[i][j]表示ij所能到达的最左端的L,R[i][j]表示i,j所能到达最右端的R

若a[i-1][j] == 0 那么L 和 R就能从i-1,j转移

能到达的最左端必然存在一个障碍或者边界挡住,右端同理

如果L,R要从上一层转移,那么新的L,R就是原先值和这一层左右离i,j最近的障碍的较劣值

显然这个可以再扫描处理为1的点时就求出来

那么对于一个点,以这个点及其悬线为中心的矩阵面积就是(R[i][j] - L[i][j] + 1) * UP[i][j]

悬线法实际上用了极大子矩阵的思想,个人能力有限,也就只能先学到这里了

下面放代码

for(int i = 1; i <= m; i++) l[i] = 1, r[i] = m;
for(int i = 1; i <= n; i++){
  int pre = 0, nxt = m + 1;
  for(int j = 1; j <= m; j++)
  if(a[i][j] == ‘1‘) pre = j, l[j] = 1; else l[j] = Max(l[j], pre + 1);
  for(int j = m; j >= 1; j--)
  if(a[i][j] == ‘1‘) nxt = j, r[j] = m; else r[j] = Min(r[j], nxt - 1);
  for(int j = 1; j <= m; j++) ans = Max(ans, (r[j] - l[j] + 1) * up[i][j]);	
}

  

 

重(zhong)新学习悬线法

标签:表示   系统   最大子矩阵   经典   能力   int   ++   左右   转移   

原文地址:http://www.cnblogs.com/mangoyang/p/7609003.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!