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 }

 

posted @ 2013-05-17 15:30  Seraph2012  阅读(269)  评论(0编辑  收藏  举报