四分树(刘汝佳-紫书)

题目:

题目链接

在这里插入图片描述
如图所示,可以用四分图来表示一个黑白图像,方法是用根节点表示整幅图像,然后把行列个分成两等份,按图中的方式编号,从左到右对应4个子节点。如果某子节点对应的区域全黑或全白,则直接用一个黑节点或白节点表示;如既有黑又有白,则用一个灰节点表示,并且为这个区域递归建树。 给出两棵四分树的先序遍历,求二者合并(黑色部分合并)黑像素的个数(每幅图都是32X32的)。p表示灰节点,f表示黑节点,e表示白节点。

样例输入:

3
ppeeefpffeefe
pefepeefe
peeef
peefe
peeef
peepefefe

样例输出

There are 640 black pixels.
There are 512 black pixels.
There are 384 black pixels.

题目分析:

首先给出一颗四分树的前序遍历,我们可以通过前序遍历得出整个四分树,p代表灰色,如果输入了p,那么意味着它内部的4个格子,一定是有白有黑。这道题我们要算出所有黑色像素点,比如8*8的正方形内部有64个像素点。

解释一组输入样例:
ppeeefpffeefe

第一个p代表整个(第一层)正方形为灰色,第二个p,代表右上角的正方形为灰色,eeef(按题中所给的标号)代表右上角正方形内部四个格子颜色为白白白黑,接下来的p代表,左上角的格子为灰色,ffee代表左上角格子内部为黑黑白白,接下来的f代表,左下角的正方形为黑色,最后的e代表,右下角的正方形为白色。

解题思路:

读入前序遍历时,遇到p我们就要把大正方形分为4个小正方形,在小正方形中遇到p,还需要在分为小小的4个正方形。显然这是一种递归思想。我们在构建整个四分树时,传入参数r,c即正方形的左下角坐标,以及读入的操作,和正方形边长。如果操作为p,那我们递归调用构建方法,每次将边长除以2,以及根据当前左下角坐标,传入新的左下角坐标,如果操作为f,我们进行染色,将以(r,c)为左下角的二维数组染色,一直染到右上角(r+w,c+w),并且每次都将黑色像素点数字加一。如果是e我们不需要操作。

实现代码:

#include <bits/stdc++.h>
using namespace std;

int len=32;//边长
const int maxn=1024+10;//32*32=2^5*2^5=2^10=1024

char s[maxn];//树最多maxn个结点,也就是maxn个操作
int buf[32][32],cnt;//存放四分树


void draw(const char* s,int &p,int r,int c,int w)//传入数组时使用指针,传入参数时使用&
{
    char ch=s[p++];//读入当前操作
    if(ch=='p')
    {
        //从编号为1开始递归(r,c)为左下角
       draw(s,p,r+w/2,c+w/2,w/2);//1
       draw(s,p,r,c+w/2,w/2);//2
       draw(s,p,r,c,w/2);//3
       draw(s,p,r+w/2,c,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)//0表示白色
            {
                buf[i][j]=1;//1表示染黑
                cnt++;
            }
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(buf,0,sizeof(buf));
        cnt=0;
        for(int i=1; i<=2; i++)
        {
            scanf("%s",s);
            int p=0;//统计读入到第几个字符
            draw(s,p,0,0,len);//初始长度为32
        }
        printf("There are %d black pixels.\n",cnt);
    }
   return 0;
}

杂记:

我们并不用担心输入的是两颗树,在输入第二颗树时,会不会对结果造成影响,因为在染色时,读入第二颗树相当于对第一颗树进行进一步染色,原来是黑色还是黑色,原来是白色,读入的是黑色,新的黑色范围会包括原来的白色,会把白色染黑,并且新的操作是染白色也不会改变原来的黑色,因为我们直接跳过了白色的操作。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值