第一次遇到四叉树的题目。紫书上相当于创建了32×32的二维数组来模拟整个大方块。而我的思路是:仿照建二叉树的方法建四叉树,只是多了两个子节点而已。分别用-1,0,1来表示当前节点的颜色,以便于合并以及计数。合并的细节我写到了注释里。计数时,将根结点(即最外层的大方块)看做拥有32×32=1024个像素点,那么第二层中,每个结点拥有1024/(2^2)个结点,以此类推。
题目链接:UVa 297
AC代码:
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
struct Node {
int data; //data三个取值-1,0,1.分别代表白、灰、黑
Node* first, * second, * third, * fourth;
Node() :first(NULL), second(NULL), third(NULL), fourth(NULL) {}
}*r, * root1, * root2;
queue<char> q;
void read_input(queue<char>& v) {
string s;
cin >> s;
while (!v.empty())
v.pop();
for (int i = 0; i < s.length(); i++)
v.push(s[i]);
}
void build(Node*& node, queue<char>& v) {
node = new Node();
if (v.front() == 'p') {
v.pop();
node->data = 0;
build(node->first, v);
build(node->second, v);
build(node->third, v);
build(node->fourth, v);
}
else if (v.front() == 'f') {
v.pop();
node->data = 1;
}
else if (v.front() == 'e') {
v.pop();
node->data = -1;
}
}
void remove(Node* u) {
if (u == NULL) return;
remove(u->first);
remove(u->second);
remove(u->third);
remove(u->fourth);
delete u;
}
void add(Node* r1, Node* r2, Node*& root) {
root = new Node();
if (r1->data == 1 || r2->data == 1) //其中一个是黑结点,合并后也是黑结点
root->data = 1;
else if (r1->data == -1 && r2->data == -1) //都是白结点,合并后才是白结点
root->data = -1;
else if (r1->data == 0 && r2->data == -1)
root = r1;
else if (r1->data == -1 && r2->data == 0) //一灰一白,合并后与灰相同
root = r2;
else { //都是灰结点,递归合并
root->data = 0;
add(r1->first, r2->first, root->first);
add(r1->second, r2->second, root->second);
add(r1->third, r2->third, root->third);
add(r1->fourth, r2->fourth, root->fourth);
}
}
int count(Node* node, int i) { //自根向下,每层黑结点代表的像素块依次减少
int n = 0;
if (node->data == 1)
n = pow(2, i);
else if (node->data == 0) {
n += count(node->first, i - 2);
n += count(node->second, i - 2);
n += count(node->third, i - 2);
n += count(node->fourth, i - 2);
}
return n;
}
int main() {
int T;
cin >> T;
while (T--) {
read_input(q), build(root1, q);
read_input(q), build(root2, q);
add(root1, root2, r);
cout << "There are " << count(r, 10) << " black pixels." << endl;
remove(r);
}
return 0;
}