UVa297 (四分树 Quadtrees)

1、题目大意

  1. 题目链接UVa 297
  2. 给出结点值为 p, e, f 的两个严格四叉树(非叶结点的度为 4)的先序遍历序列,p 代表灰色,e 代表白色,f 代表黑色,将两个树对应的结点颜色相融合,求最终黑结点代表的像素个数。其中根结点代表像素数为1024个,其余每个结点代表的像素数为上一层结点的四分之一。

2、解题思路

  1. 根据先序序列就可以确定这个四叉树。因为本题中,严格四叉树的结点个数为 4n+1 个,如果结点值为 p,则该结点有子树;如果结点值为 e 或 f ,则该结点没有子树。
  2. 根据两个先序序列分别递归建树 tree1 和 tree2。
  3. 根据规则合并两个树,合并的结果存到 tree1 中。
  4. 遍历树 tree1 ,统计黑色结点代表的像素的个数。

3、参考代码

#include<iostream>
#include<string>

using namespace std;

struct node {
	char color;
	node *n1, *n2, *n3, *n4;
	node() :color('e'), n1(NULL), n2(NULL), n3(NULL), n4(NULL) {}
};

node* build(string& s, int& pos) {
	node* root = new node();
	root->color = s[pos];
	if (s[pos] == 'p') {
		pos++; root->n1 = build(s, pos); pos++; root->n2 = build(s, pos);
		pos++; root->n3 = build(s, pos); pos++; root->n4 = build(s, pos);
	}
	return root;
}

void merge(node* tree1, node* tree2) {
	if (tree2->color == 'f') {
		tree1->color = 'f';
		tree1->n1 = tree1->n2 = tree1->n3 = tree1->n4 = NULL;
	}
	else if (tree2->color == 'p' && tree1->color != 'f') {
		if (tree1->color == 'e') {
			tree1->n1 = tree2->n1; tree1->n2 = tree2->n2;
			tree1->n3 = tree2->n3; tree1->n4 = tree2->n4;
		}
		tree1->color = 'p';
		merge(tree1->n1, tree2->n1); merge(tree1->n2, tree2->n2);
		merge(tree1->n3, tree2->n3); merge(tree1->n4, tree2->n4);
	}
}

int cnt(node* tree, int level) {
	int sum = 0;
	if (tree == NULL) return 0;
	if (tree->color == 'f')
		sum += 1024 / level;
	sum += cnt(tree->n1, level * 4);
	sum += cnt(tree->n2, level * 4);
	sum += cnt(tree->n3, level * 4);
	sum += cnt(tree->n4, level * 4);
	return sum;
}


int main() {
	int n;
	cin >> n;
	while (n--) {
		string s;
		cin >> s;
		int pos = 0;
		node* tree1 = build(s, pos);
		cin >> s;
		pos = 0;
		node* tree2 = build(s, pos);
		merge(tree1, tree2);
		cout << "There are " << cnt(tree1, 1) << " black pixels." << endl;
	}
	return 0;
}

刘大爷书上的代码:

//刘大爷思路,直接模拟画出这个 32*32 的黑白图像的过程,边画边统计黑色结点的个数。
#include<iostream>
#include<string>
#include<cstring>

using namespace std;

int cnt;
int pic[32][32];

//把字符串“画”到 以(r, c)为左上顶点,宽度为 w 的图像 pic 中。
void draw(string& s, int& pos, int r, int c, int w) {
	if (s[pos] == 'p') {
		draw(s, ++pos, r + w / 2, c        , w / 2);
		draw(s, ++pos, r + w / 2, c + w / 2, w / 2);
		draw(s, ++pos, r        , c        , w / 2);
		draw(s, ++pos, r        , c + w / 2, w / 2);
	}
	else if (s[pos] == 'f') {
		for (int i = r; i < r + w; i++)
			for (int j = c; j < c + w; j++)
				if (pic[i][j] == 0) {
					pic[i][j] = 1;
					cnt++;
				}
	}
}

int main() {
	int n;
	cin >> n;
	while (n--) {
		memset(pic, 0, sizeof(pic));
		cnt = 0;
		string s;
		int pos = 0;
		cin >> s;
		draw(s, pos, 0, 0, 32);
		pos = 0; cin >> s;
		draw(s, pos, 0, 0, 32);
		cout << "There are " << cnt << " black pixels." << endl;
	}
	return 0;
}

4、解题感悟

  1. 刘大爷这个思路太妙了!直接模拟画出这个图像的过程,同时统计黑色像素的数目。思路很清晰,代码也很简单。
  2. 思考问题产生的过程,设置合理的数据结构,然后去模拟这个过程,进而解决这个问题。这可能就是所谓的面向对象编程思想吧。
  3. 多思考,多总结。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值