題意思路:DP.
一開始我用二維樹狀數(shù)組去搞。死在最優(yōu)一組數(shù)據(jù)上(全1)。因?yàn)槟菢佑泻芏嗬速M(fèi)的操作。可是想不出什么好辦法,無(wú)奈問了好多人。diy群的神牛們一致說(shuō)dp,baihacker大神的做法好像就這樣的.水平太弱,聽不懂。后來(lái)還是在一個(gè)朋友的指點(diǎn)下領(lǐng)悟了dp的思想。具體如下
設(shè)dp[i][j] 為以(i,j)為左上角的符合情況的邊的最大長(zhǎng)度。那么我們可以得到長(zhǎng)度為k的方陣的個(gè)數(shù)等于那些dp[i][j]>=k的個(gè)數(shù)。
用樣例來(lái)說(shuō)的話
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的個(gè)數(shù)就是dp[i][j] >= 2的數(shù)目也就是6(2的個(gè)數(shù))+3(3的個(gè)數(shù))+1(4的個(gè)數(shù))=10
3和4同理
那么現(xiàn)在要求的就是所有dp[i][j]了。我們可以得到如下轉(zhuǎn)移方程。
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;
到這里基結(jié)束了。官方的有兩種做法,也都是dp。第一種是n^3的,這里就不說(shuō)了。第二種是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