题目:https://cn.vjudge.net/problem/UVA-297
这个题目非正常的二分树,是四分树,在做题前读清题意;
题意:大正方形可以划分出四个小正方形,最大正方形的边长为32像素,且每一次分成的小正方形按逆时针编号为1,2,3,4。这样的划分可以用四分树来表示,且可以用先序的方式输入。四分树的节点有三种表示方式,f: 所划分出来的四个小块全为黑 e:所划分出来的四个小块全为白 p:所划分出来的四个小块既有黑也有白。 输入两棵四分树,使两个树相加,规则看图。最后需要求得黑色块的个数。(注:每个像素是一个 小块,也就是说大的正方形一共有32*32=1024个像素块)
对于这个题目我举一个例子,
对于这样一个分块的长条:
要求进行两次操作,每一次操作可以涂黑若干个方块,问两次一共涂黑了多少个方块。
对于这个问题我们可以这样解,设一个全局变量,在涂黑前判断是否已经涂黑,若没有则涂黑,则涂黑给全局变量+1,则两次操作后的全局变量的结果就是最终的答案,这个操作就是边涂边统计的。
理解了上面的操作扩展到二维上来就是本题了。一个32*32的正方形,每一个小正方形都可以被涂黑,问两次一共涂了多少黑块。
#include <bits/stdc++.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
//#define LOCAL
using namespace std;
const int maxn=1024+10;
const int len=32; ///每个正方形边长是32
char s[maxn];
int buf[len][len],cnt;
void draw(const char*s,int &p,int r,int c,int w) ///r c代表画图的左上角坐标 w代表边长
{
char ch=s[p++];
if(ch=='p')
{
draw(s,p,r, c+w/2,w/2);
draw(s,p,r, c,w/2);
draw(s,p,r+w/2, c,w/2);
draw(s,p,r+w/2, c+w/2,w/2);
}else if(ch=='f')
{
for(int i=r;i<r+w;i++) ///这一块不好理解 需理解为什么是要<r+w 不直接是(r,c)这个点,因为这是一棵四分树
for(int j=c;j<c+w;j++) ///从根节点开始是代表的整个大正方形,每下降一层所代表的正方形就会变成上一层的1/4
if(buf[i][j]==0) {buf[i][j]=1;cnt++;}///既然代表大正方形,大正方形每条边都很会包含相应的最小的像素块数,所以这里要像二维数组那样,涉及到每一块
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int t;cin>>t;
while(t--)
{
memset(buf,0,sizeof buf);
cnt=0;
for(int i=0;i<2;i++)
{
scanf("%s",s);
int p=0;
draw(s,p,0,0,len);
}
printf("There are %d black pixels.\n",cnt);
}
return 0;
}