题意思路:DP.
一开始我用二维树状数组去搞。死在最优一组数据上(全1)。因为那样有很多浪费的操作。可是想不出什么好办法,无奈问了好多人。diy群的神牛们一致说dp,baihacker大神的做法好像就这样的.水平太弱,听不懂。后来还是在一个朋友的指点下领悟了dp的思想。具体如下
设dp[i][j] 为以(i,j)为左上角的符合情况的边的最大长度。那么我们可以得到长度为k的方阵的个数等于那些dp[i][j]>=k的个数。
用样例来说的话
dp[i][j]如下
1 0 4 2 3 1
0 0 3 3 2 1
1 1 2 2 2 1
0 0 2 1 1 1
0 0 1 1 0 1
1 1 1 0 0 1
那么2的个数就是dp[i][j] >= 2的数目也就是6(2的个数)+3(3的个数)+1(4的个数)=10
3和4同理
那么现在要求的就是所有dp[i][j]了。我们可以得到如下转移方程。
if(0 == num[i][j])/*num存的是原矩阵*/
dp[i][j] = 0;/*矩阵含0不符合情况*/
else
dp[i][j] = min(dp[i+1][j],dp[i][j+1],dp[i+1][j+1])+1;
到这里基结束了。官方的有两种做法,也都是dp。第一种是n^3的,这里就不说了。第二种是n^2的。而且空间也比较小,这里贴下。
官方
1Greg Price writes:
2
3The posted solution runs in cubic time, with quadratic storage. With a little more cleverness in the dynamic programming, the task can be accomplished with only quadratic time and linear storage, and the same amount of code and coding effort. Instead of running back along the rows and columns from each square, we use the biggest-square values immediately to the west and north, so that each non-ravaged square's biggest-square value is one more than the minimum of the values to the west, north, and northwest. This saves time, bringing us from cubic to quadratic time.
4
5Another improvement, which saves space and perhaps cleans up the code marginally, is to keep track of the number of squares of a given size as we go along. This obviates the need to keep a quadratic-size matrix of biggest-square values, because we only need the most recent row for continuing the computation. As for "ravaged" values, we only use each one once, all in order; we can just read those as we need them.
6
7#include <fstream.h>
8
9ifstream fin("range.in");
10ofstream fout("range.out");
11
12const unsigned short maxn = 250 + 5;
13
14unsigned short n;
15char fieldpr;
16unsigned short sq[maxn]; // biggest-square values
17unsigned short sqpr;
18unsigned short numsq[maxn]; // number of squares of each size
19
20unsigned short
21min3(unsigned short a, unsigned short b, unsigned short c)
22{
23 if ((a <= b) && (a <= c))
24 return a;
25 else
26 return (b <= c) ? b : c;
27}
28
29void
30main()
31{
32 unsigned short r, c;
33 unsigned short i;
34 unsigned short tmp;
35
36 fin >> n;
37
38 for (c = 1; c <= n; c++)
39 sq[c] = 0;
40
41 for (i = 2; i <= n; i++)
42 numsq[i] = 0;
43
44 for (r = 1; r <= n; r++)
45 {
46 sqpr = 0;
47 sq[0] = 0;
48 for (c = 1; c <= n; c++)
49 {
50 fin >> fieldpr;
51 if (!(fieldpr - '0'))
52 {
53 sqpr = sq[c];
54 sq[c] = 0;
55 continue;
56 }
57
58 // Only three values needed.
59 tmp = 1 + min3(sq[c-1], sqpr, sq[c]);
60 sqpr = sq[c];
61 sq[c] = tmp;
62
63 // Only count maximal squares, for now.
64 if (sq[c] >= 2)
65 numsq[ sq[c] ]++;
66 }
67 }
68
69 // Count all squares, not just maximal.
70 for (i = n-1; i >= 2; i--)
71 numsq[i] += numsq[i+1];
72
73 for (i = 2; i <= n && numsq[i]; i++)
74 fout << i << ' ' << numsq[i] << endl;
75}
76
77
78