6-11 四分树(Quadtrees, UVa 297)

如图6-8所示,可以用四分树来表示一个黑白图像,方法是用根结点表示整幅图像,然 后把行列各分成两等分,按照图中的方式编号,从左到右对应4个子结点。如果某子结点对 应的区域全黑或者全白,则直接用一个黑结点或者白结点表示;如果既有黑又有白,则用一 个灰结点表示,并且为这个区域递归建树。
给出两棵四分树的先序遍历,求二者合并之后(黑色部分合并)黑色像素的个数。p表 示中间结点,f表示黑色(full),e表示白色(empty)。
样例输入:
3
ppeeefpffeefe
pefepeefe
peeef
peefe
peeef
peepefefe
样例输出:
There are 640 black pixels.
There are 512 black pixels.
There are 384 black pixels.
【分析】
由于四分树比较特殊,只需给出先序遍历就能确定整棵树(想一想,为什么)。只需要 编写一个“画出来”的过程,边画边统计即可。

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstring>
#include <queue>
#define outchar(ch) printf("%c",ch)
using namespace std;

struct node {
	char value;
	node  *son = nullptr;
};
char rebuild(node &r)
{
	char ch = cin.get();
	if (ch == 'p')
	{
		r.son = new node[4];
		for (int i = 0; i < 4; ++i)
			r.son[i].value = rebuild(r.son[i]);
	}
	return ch;
}
char colorplus(char x, char y)
{
	if (x == y)
		return x;
	else if (x == 'f' || y == 'f')
		return 'f';
	else if (x == 'p' || y == 'p')
		return 'p';
}
char merge(node &x,node &y,node &r)
{
	char result = colorplus(x.value, y.value);
	if (result == 'p')
	{
		r.son = new node[4];
		if (x.value == y.value)
		{
			for (int i = 0; i < 4; ++i)
				r.son[i].value = merge(x.son[i], y.son[i], r.son[i]);
		}
		else {
			if (x.value == 'p')
				r.son = x.son;
			else r.son = y.son;
		}
	}
	return result;
}
inline int nums(int x)
{
	return x == 1 ? 1 : x <= 5 ? 256 : x <= 25 ? 64 : x <= 85 ? 16 : x <= 341 ? 4 : x <= 1365 ? 1 : 1;
}
int  calc(const node &r)//层序遍历 并根据黑色像素所在层计算其值  算出所有黑色像素值的总和
{
	int count = 1, sum = 0;
	queue<node> q;
	q.push(r);
	while (!q.empty())
	{
		char ch = q.front().value;
		if (ch == 'f')
			sum += nums(count);
		if (q.front().son != nullptr)
			for (int i = 0; i < 4; ++i)
				q.push(q.front().son[i]);
		q.pop(), count++;
	}
	return sum;
}
char str[1000];
int main()
{
	int nums;
	(cin >> nums).get();
	while (nums--)
	{
		node r, l, result;
		r.value = rebuild(r),cin.get();
		l.value = rebuild(l),cin.get();
		result.value = merge(r, l, result);
		cout << "There are " << calc(result) << " black pixels" << endl;
	}	
	return 0;
}
//other
void traversal(const node &r)//前序遍历打印
{
	outchar(r.value);
	if (r.value == 'p')
		for (int i = 0; i < 4; ++i)
			traversal(r.son[i]);
}
void layer_traversal(const node &r)//层序遍历打印
{
	queue<node> q;
	q.push(r);
	while (!q.empty())
	{
		outchar(q.front().value);
		if (q.front().son != nullptr)
		{
			for (int i = 0; i < 4; ++i)
				q.push(q.front().son[i]);
		}
		q.pop();
	}
}
/*
3
ppeeefpffeefe
pefepeefe
peeef
peefe
peeef
peepefefe

*/
/*  bug
void rebuild(node &r, char *str, int index)
{
if (index >= strlen(str)) return;
char c = str[index++];
r.value = c;
if (c == 'p')
{
r.son = new node[4];
rebuild(r.son[0], str, index++);
rebuild(r.son[1], str, index++);
rebuild(r.son[2], str, index++);
rebuild(r.son[3], str, index++);
}
}

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值