建造四叉树是个难点,何时知道有四个儿子结点已经入栈呢?答案是当栈顶连续四个结点都是某个结点的儿子时,就应该将其出栈合成一个父亲结点,并且入栈。而且如果某层的结点是黑,那么它下方的结点就不用再考虑了,因为合成时是优先选择面积最大的黑色块 #include <iostream> #include <cstring> #include <cstdlib> using namespace std ; const int maxn = 2048 + 10 ; struct Node { Node * a ; Node * b ; Node * c ; Node * d ; char data ; bool visit ; } ; int top ; int ans ; Node * Stack[maxn] ; char str1[maxn] , str2[maxn] ; int fix[] = { 32 * 32 , 16 * 16 , 8 * 8 , 4 * 4 , 2 * 2 , 1 * 1 } ;//每层像素的数值 //初始化 void init() { ans = 0 ; memset( str1 , 0 , sizeof( str1 ) ) ; memset( str2 , 0 , sizeof( str2 ) ) ; return ; } //创建结点 Node * creatNode( char data ) { Node * node = new Node ; node -> a = NULL ; node -> b = NULL ; node -> c = NULL ; node -> d = NULL ; node -> data = data ; return node ; } //往树上增加结点 Node * addNode( char data , Node * a , Node * b , Node * c , Node * d ) { Node * father = new Node ; father -> a = a ; father -> b = b ; father -> c = c ; father -> d = d ; father -> data = data ; return father ; } //建立四叉树 Node * buildTree( char s[] ) { memset( Stack , 0 , sizeof( Stack ) ) ;//初始化结点栈 top = 0 ; int len = strlen( s ) ; int count = 0 ; for( int i = 0 ; i < len ; i++ ) { if( s[i] == 'f' || s[i] == 'e' ) { Node * p = creatNode( s[i] ) ; top++ ; Stack[top] = p ; Stack[top] -> visit = true ; } if( s[i] == 'p' ) { Node * p = creatNode( s[i] ) ; top++ ; Stack[top] = p ; Stack[top] -> visit = false ; } if( top > 4 ) { int ok = 0 ; int flag = 1 ; for( int j = top - 3 ; j <= top ; j++ ) if( ! Stack[j] -> visit ) { ok = 1 ; break ; } if( ok ) flag = 0 ; while( flag )//当某结点的四个连续的子结点在栈中 { //出栈合成一个父结点并说明他是该父结点的子结点 Node * d = Stack[top] ; Stack[top] -> visit = false ; top-- ; Node * c = Stack[top] ; Stack[top] -> visit = false ; top-- ; Node * b = Stack[top] ; Stack[top] -> visit = false ; top-- ; Node * a = Stack[top] ; Stack[top] -> visit = false ; top-- ; Node * father = Stack[top] ; Stack[top] -> visit = false ; top-- ; Node * ffather = addNode( father -> data , a , b , c , d ) ; Stack[++top] = ffather ; Stack[top] -> visit = true ; if( top > 4 )//一直合到不再有符合条件的结点组合为止 { for( int i = top - 3 ; i <= top ; i++ ) if( ! Stack[i] -> visit ) { ok = 1 ; break ; } if( ok ) flag = 0 ; } else flag = 0 ; } } } Node * root = Stack[top] ; return root ; } //深度优先遍历树 void dfs( Node * u1 , Node * u2 , int floor ) { if( u1 -> data == 'f' || u2 -> data == 'f' )//当该结点为f说明该结点以下的结点都不用访问,加上该层像素的数值 { ans += fix[floor] ; return ; } else {//为了遍历下面结点,为空结点开辟空间,为了不影响结果,将其值赋为不相干的东西,我的为t if( u1 -> a || u2 -> a ) { if( ! u1 -> a ) u1 -> a = creatNode( 't' ) ; else if( ! u2 -> a ) u2 -> a = creatNode( 't' ) ; dfs( u1 -> a , u2 -> a , floor + 1 ) ;//递归遍历大儿子 } if( u1 -> b || u2 -> b ) { if( ! u1 -> b ) u1 -> b = creatNode( 't' ) ; else if( ! u2 -> b ) u2 -> b = creatNode( 't' ) ; dfs( u1 -> b , u2 -> b , floor + 1 ) ;//递归遍历二儿子 } if( u1 -> c || u2 -> c ) { if( ! u1 -> c ) u1 -> c = creatNode( 't' ) ; else if( ! u2 -> c ) u2 -> c = creatNode( 't' ) ; dfs( u1 -> c , u2 -> c , floor + 1 ) ;//递归遍历三儿子 } if( u1 -> d || u2 -> d ) { if( ! u1 -> d ) u1 -> d = creatNode( 't' ) ; else if( ! u2 -> d ) u2 -> d = creatNode( 't' ) ; dfs( u1 -> d , u2 -> d , floor + 1 ) ;//递归遍历小儿子 } } } int main() { int ncase ; cin >> ncase ; getchar() ; while( ncase-- ) { init() ; gets( str1 ) ; gets( str2 ) ; Node * root1 = buildTree( str1 ) ; Node * root2 = buildTree( str2 ) ; dfs( root1 , root2 , 0 ) ; cout << "There are " << ans << " black pixels." << endl ; } return 0 ; }