zoukankan      html  css  js  c++  java
  • hdu 2483

    地址:http://acm.hdu.edu.cn/showproblem.php?pid=2483

    题意:给一个n*m的0-1矩阵。在里面找符合条件的方阵。条件有3个:1.方阵的4条边上全为1;2.方阵内(除了4条边的)0和1的个数之差不超过1;3.方阵大小至少为2*2。问能找到几个这样的方针。

    mark:最朴素的做法是枚举所有的1当做要找的方阵左上角的元素。然后判断四边是否全为1,再统计内部0和1的个数。但是每次判断边上的1和计算内部1的数量复杂度太高,肯定是不行的。

    我们用一个数组sum[i][j]表示从矩形左上角到(i,j)这个位置里1的个数。在计算区域内1的个数的时候可以利用这个sum[i][j]数组得到。sum[i][j]需要预处理出来:sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j]。

    我们用一个数组row[i][j]表示第i行中第j个元素是“连续的第几个1”。例如111011对应的row[i]就是123012。判断横边是否是连续的1的时候,可以用row[i][right]-row[i][left-1]的结果和right-left比较,相同则全为1。row数组需要预处理出来:row[i][j] = (g[i][j]?row[i][j-1]+1:0);

    竖边也是这样预处理出来。

    这样判断一个给定的方阵是否符合要求,只需要利用上面3个辅助数组,O(1)地完成,复杂可以符合要求了。

    代码:

     1 # include <stdio.h>
     2 # include <string.h>
     3 
     4 
     5 int g[310][310] ;
     6 int sum[310][310] ;
     7 int row[310][310], col[310][310] ;
     8 int n, m ;
     9 
    10 
    11 int abs(int x){return x<0?-x:x;}
    12 
    13 
    14 int check(int x, int y, int xx, int yy)
    15 {
    16     int _1 = sum[xx-1][yy-1]-sum[xx-1][y]-sum[x][yy-1]+sum[x][y] ;
    17     int _0 = (xx-x-1)*(yy-y-1) - _1 ;
    18     if (abs( _1 - _0) > 1) return 0 ;
    19     if (row[x][yy] - row[x][y] != yy-y) return 0 ;
    20     if (row[xx][yy]-row[xx][y] != yy-y) return 0 ;
    21     if (col[xx][y] - col[x][y] != xx-x) return 0 ;
    22     if (col[xx][yy] - col[x][yy] != xx-x) return 0 ;
    23     return 1 ;
    24 }
    25 
    26 
    27 int main ()
    28 {
    29     int T ;
    30     int i, j, k ;
    31     int l, t, r, d, ans ;
    32     int flag ;
    33     
    34     scanf ("%d", &T) ;
    35     while (T--)
    36     {
    37         scanf ("%d%d", &n, &m) ;
    38         for (i = 1 ; i <= n ; i++)
    39             for (j = 1 ; j <= m ; j++)
    40                 scanf ("%d", &g[i][j]),
    41                 sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j],
    42                 row[i][j] = ((g[i][j])?(row[i][j-1]+1):0),
    43                 col[i][j] = ((g[i][j])?(col[i-1][j]+1):0) ;
    44         ans = 0 ;    
    45         for (i = 1 ; i <= n ; i++)
    46             for (j = 1 ; j <= m ; j++) if (g[i][j])
    47                 for (k = 1 ; i+k<=n && j+k<=m ; k++)
    48                     if (check(i,j,i+k,j+k))    ans++ ;
    49         printf ("%d\n", ans) ;
    50     }
    51     return 0 ;
    52 }
  • 相关阅读:
    java命令模式
    java中介者模式
    java访问者模式
    java状态模式
    java责任链模式
    java策略模式(及与工厂模式的区别)
    github token 位置
    Yii2 Queue队列
    sz与rz
    vim
  • 原文地址:https://www.cnblogs.com/lzsz1212/p/3083768.html
Copyright © 2011-2022 走看看