题目:我谷
代码:
#include <cstdio>
#include <cstring>
#define null NULL
char s1[100001],s2[100001];
struct node
{
char c;
node *ch[5];//孩子数组
node()
{
c=0;
ch[1]=ch[2]=ch[3]=ch[4]=null;//初始化为NULL
}
node(char _c)//字符构造函数
{
c=_c;
ch[1]=ch[2]=ch[3]=ch[4]=null;
}
};
char *cur;//make函数使用,表示当前处理的字符
node *make()
{
if(*cur=='f')
{
node *tmp=new node('f');//返回黑节点
return tmp;
}
if(*cur=='e')
{
node *tmp=new node('e');//返回白节点
return tmp;
}
if(*cur=='p')
{
node *tmp=new node('p');//首先现将该节点的颜色设为灰
for(int i=1;i<=4;++i)
{
++cur;//指针后移
tmp->ch[i]=make();//递归构建子树
}
return tmp;//返回节点
}
return null;//防CE
}
node *add(node *n1,node *n2)
{
if(n1==null&&n2==null)//只是为了保险
{
return null;
}
if(n1==null||n2==null)
{
return n1==null?n2:n1;
}
if(n1->c=='f'||n2->c=='f')//有一个黑节点
{
node *tmp=new node('f');
return tmp;
}
else if(n1->c=='e'&&n2->c=='e')//全是白节点
{
node *tmp=new node('e');
return tmp;
}
else
{
node *tmp=new node('p');//新建灰节点
bool full=true;//此变量是为了计算是否合并完之后变成黑节点,比如▚和▞
for(int i=1;i<=4;++i)
{
tmp->ch[i]=add(n1->ch[i],n2->ch[i]);//递归合并子树
if(tmp->ch[i]->c!='f')//如果有一个像素不为黑则不设置为黑
{
full=false;
}
}
if(full)//如果是黑节点
{
tmp=new node('f');//更新
}
return tmp;
}
return null;
}
int count(node *n1,int dep)//n1为当前节点,dep为当前深度
{
if(n1==null)
{
return 0;
}
if(n1->c=='f')//黑节点
{
return (1024>>(dep*2));//计算该节点的像素数
}
if(n1->c=='e')//空节点
{
return 0;//直接返回0
}
if(n1->c=='p')
{
int ans=0;
for(int i=1;i<=4;++i)
{
ans+=count(n1->ch[i],dep+1);//递归数像素
}
return ans;//返回
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",s1+1,s2+1);
cur=s1+1;//处理指针置为第一个字符串开头
node *r1,*r2;//根节点
r1=make();
cur=s2+1;//同上
r2=make();
node *root=add(r1,r2);
printf("There are %d black pixels.\n",count(root,0));//输出个数
}
return 0;
}
1.建树
如果当前像素是f,那么直接设成黑像素即可
如果当前像素是e,同理
如果为p,则需要递归扩展子树
2.相加
首先如果当前像素中有黑色,那么结果一定为黑
如果全为白,那么结果为白
否则递归扩展4个子树
3.数像素
如果为黑,则返回2^{10-dep*2}2
10−dep∗2
如果为白,则返回00
否则还是递归扩展4个子树