題意思路: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的。而且空間也比較小,這里貼下。

官方
1
Greg Price writes:
2
3
The 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
5
Another 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
9
ifstream fin("range.in");
10
ofstream fout("range.out");
11
12
const unsigned short maxn = 250 + 5;
13
14
unsigned short n;
15
char fieldpr;
16
unsigned short sq[maxn]; // biggest-square values
17
unsigned short sqpr;
18
unsigned short numsq[maxn]; // number of squares of each size
19
20
unsigned short
21
min3(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
29
void
30
main()
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