白书 例题6-11
用四分树来表示一个黑白图像:最大的图为根,然后按照图中的方式编号,从左到右对应4个子结点。如果某子结点对应的区域全黑或者全白,则直接用一个黑结点或者白结点表示;如果既有黑又有白,则用一个灰结点表示,并且为这个区域递归建树。
思路
用一个buffer表示黑白表格,利用递归建树,每当遇见p(灰色)就往下递归四个节点,遇到f(黑色)就把buf[][]
对应的位置设为1
cuf++,找对应的位置
是个难点.需要遍历(r,r+w)(c,c+w)r,c是buf的下标,从左上角开始,w是格子的大小,初始为总len=32,每递归一层,除2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#include
"cstdio"
#include
"cstring"
#include
"iostream"
#include
"cmath"
#include
"cstring"
#include
"cstring"
#include
"cstdio"
#pragma
warning(disable:4996)
const
int
len
=
32;//边长
const
int
maxn
=
1024
+
10;
char
s[maxn];
int
buf[len][len],
cnt;//指针
//
s是读入的字符串序列,p当前正在读的字符串的下标,r是纵坐标,c是横坐标,w是当前块的大小,从len开始,深度+1,w/=2.
void
draw(const
char*
s,
int&
p,
int
r,
int
c,
int
w)
{
char
ch
=
s[p++];
if
(ch
==
'p')
{//灰色,读取子树
draw(s,
p,
r,
c
+
w
/
2,
w
/
2); //块1
draw(s,
p,
r,
c,
w
/
2); //块2
draw(s,
p,
r
+
w
/
2,
c,
w
/
2); //块3
draw(s,
p,
r
+
w
/
2,
c
+
w
/
2,
w
/
2);//块4
}
else
if
(ch
==
'f')
{//黑色
for
(int
i
=
r;
i
<
r
+
w;
i++)
{
for
(int
j
=
c;
j
<
c
+
w;
j++)
{
if
(buf[i][j]
==
0)
{
buf[i][j]
=
1;
cnt++;//黑块计数
}
}
}
}
}
int
main()
{
int
T;
scanf("%d",
&T);
while
(T--)
{
memset(buf,
0,
sizeof(buf));
cnt
=
0;
for
(int
i
=
0;
i
<
2;
i++)
{//读取两棵树,操作同一个buf,达到合并的目的
scanf("%s",
s);
int
p
=
0;
draw(s,
p,
0,
0,
len);
}
printf("%d",
cnt);
}
return
0;
}
|