ZOJ 1788 Quad Trees (四分樹經典)

Quad Trees

題目傳送門~

Time Limit: 2000 msMemory Limit: 65536 KB

A binary image, such as the one shown in Figure 2(a), is usually represented as an array of binary entries, i.e., each entry of the array has value 0 or 1. Figure 2(b) shows the array that represents the binary image in Figure 2(a). To store the binary image of Figure 2(b), the so-called quad tree partition is usually used. For an N N array, N <= 512 and N = 2^i for some positive integer i, if the entries do not have the same value, then it is partitioned into four N/2 N/2 arrays, as shown in Figure 2(c). If an N/2N/2 array does not have the same binary value, such as the upper right and lower right N/2N/2 arrays in Figure 2(c), then we can divide it into four N/4N/4 arrays again. These N/4N/4 arrays in turn can also, if needed, be divided into four N/8 N/8 arrays, etc.. The quad tree partition is completed when the whole array is partitioned into arrays of various size in which each array contains only one binary value. Figure 2(c) contains the arrays after the quad tree partition is completed.

 
Figure 2: A binary image (a), its array representation (b), its quad tree partition (c), and its quad tree representation (d).

Instead of storing the binary image of Figure 2(a), we only need to store the quad tree in the form as Figure 2(d) which is encoded from Figure 2(c). In Figure 2(d), each node represents an array of Figure 2(c) in which the root node represents the original array. If the value of a node in the tree is 1, then it means that its corresponding array needs to be decomposed into four smaller arrays. Otherwise, a node will have a pair of values and the first one is 0. It means that its corresponding array is not necessary to decompose any more. In this case, the second value is 0 (respectively, 1) to indicate that all the entries in the array are 0 (respectively, 1). Thus, we only need to store the tree of Figure 2(d) to replace storing the binary image of Figure 2(a). The way to store the tree of Figure 2(d) can be represented by the following code:

(1)(0,0)(1)(0,1)(1)(0,0)(0,1)(1)(0,0)(0,0)(0,0)(0,1)(0,1)(0,0)(0,1)(0,0)(0,1).

This code is just to list the values of the nodes from the root to leaves and from left to right in each level. Deleting the parentheses and commas, we can obtain a binary number 100101100011000000010100010001 which is equal to 258C0511 in hexadecimal. You are asked to design a program for finding the resulting hexadecimal value for each given image.


Input

There is an integer number k, 1 <= k <= 100, in the first line to indicate the number of test cases. In each test case, the first line is also a positive integer N indicating that the binary image is an N N array, where N <= 512 and N = 2^i for some positive integer i. Then, an N N binary array is followed in which at least one blank is between any two elements.


Output

The bit stream (in hexadecimal) used to code each input array.


Sample Input

3
2
0 0
0 0
4
0 0 1 1
0 0 1 1
1 1 0 0
1 1 0 0
8
0 0 0 0 0 0 1 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 0
0 0 0 0 0 1 0 0
1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1


Sample Output

0
114
258C0511


題後兩句話:

①啊啊啊啊啊這個四分樹是真的冷門而且不簡單,理解還挺好理解的,就是要考慮的細節超級多哭遼。

②順一波題意康康:輸入一個整數num:1 ~100,表示測試的組數,然後每組測試數據先輸入一個整數N,N <= 512且N是2的次冪,然後輸入一個N*N的0,1矩陣。如果整個N*N的矩陣是全0(或者全1),則記錄爲00(或者01),不用繼續拆分;否則,記錄爲1,並將矩陣四分爲西北、東北、西南、東南各一塊,並按此順序檢查各個分塊是否全0或全1, 不是的話繼續四分,最後把所有的01串連起來,轉換爲十六進制輸出即可。

③可能很隨便的一想就感覺先檢查,然後四分,再檢查再四分吧啦吧啦這樣下去,但是如果某組矩陣維度過高則會使檢查的時間開銷大大增加,可能就TLE遼嚶嚶嚶嚶...所以我的思路是先把整個矩陣四分到不可再分,再逐一檢查每個分叉,進行合併剪枝的操作,這樣就避免了大面積檢查浪費時間的情況。

④然後就是要把四分樹中的0,1數字串用層次遍歷的方法讀取出來,再以四位爲一個單位計算出十進制數並轉化成十六進制輸出。

⑤歸結起來整體思路就是:

(1)深度優先生成四分樹  (2)層次遍歷四分樹得到二進制數列  (3)將二進制數列轉化爲十六進制輸出

⑥學到一個tip就是怎麼輸出八或者十六進制的數(詳情看代碼)


廢話不多說了,上才藝!!!

#include<iostream>
#include<cstring>
#include<cstdio> 
#include<queue>
using namespace std;

class quadtree{  //四分樹類 
	public:
		char value[3];  //取值"00","01","1"(其中00表示全0, 01表示全1, 1表示mixed 
		quadtree *child[4];
		quadtree(){
			child[0]=child[1]=child[2]=child[3]=0;
		} 
		bool operator ==(const quadtree& p) const{  //運算符重載 
			if(strcmp(value,"1")==0||strcmp(value,p.value)!=0) return 0;  //如果有孩子值爲1或者存在相異值則不能合併 
			else return 1;
		}
		
}; 

quadtree *head;
char map[520][520],ans[10000],str[5];
int N,a[2500];

//組織輸入並進行初始化 
void init(){  
	scanf("%d",&N);
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			cin>>map[i][j];
	str[4]=0;
	memset(ans,0,sizeof(ans));
} 

//深度優先之四分樹的四分,合併,剪枝 
quadtree * DFS(int r, int c, int len)//r ,c 座標,len長度
{
	quadtree*temp = new quadtree;
	
	if(len==1){  //到四分到最小格時停止 
		temp->value[0]='0';  //第一個數 置0 
		temp->value[1]=map[r][c];  //第二個數則爲方格中的數字 
		temp->value[2]=0;  //最後一位 置0 表示結束符 
		return temp;
	}
	
	len/=2;  //將map四分 
	temp->child[0]=DFS(r,c,len);
	temp->child[1]=DFS(r,c+len,len);
	temp->child[2]=DFS(r+len,c,len);
	temp->child[3]=DFS(r+len,c+len,len);
	
	bool flag=true;
	for(int i=1;i<4;i++)  //判斷是否符合合併要求 
		if(!(*temp->child[0]==*temp->child[i])){ flag=false;break;}
	
	if(flag)  //若滿足要求則合併 
	{
		strcpy(temp->value, temp->child[0]->value);
		for (int i = 0; i < 4; i++){
			delete temp->child[i];  //剪枝 
			temp->child[i]=0;
		}
	}
	else 
		strcpy(temp->value, "1");  //否則該節點不合並,並且節點值爲1 
	return temp;
}

//將二進制轉化爲十進制數
void funtion(char s[]){
	int sum=0;
	for(int i=0;i<4;i++) sum=sum*2+str[i];
	printf("%X",sum);
}

//層次遍歷取出二進制數字字符串,並轉爲十六進制輸出
void print(){
	int i,j,m;
	
	quadtree *temp;
	queue<quadtree *> q;
	q.push(head);
	while(!q.empty()){
		temp=q.front();q.pop();
		strcat(ans,temp->value);  //將二進制串連接起來
		if(!(temp->child[0]==0))  //若該節點存在孩子
		 	for(i=0;i<4;i++) q.push(temp->child[i]);
		delete temp; 
	}
	
	int slen =strlen(ans);  //計算ans的長度 
	int pos=0;  //標記ans當前計算的位置 
	
	//爲了方便計算,將整個數字串長度補成4的倍數
	//用長度求餘數得i,在最前面補4-i個0
	if(slen%4!=0){
		i=slen%4;
		for(j=0;j<4-i;j++) str[j]=0;
		for(m=j;m<4;m++) str[m]=ans[pos++]-'0'; 
		funtion(str);
	}
	
	for(i=pos;i<slen;i+=4){
		for(j=0;j<4;j++) str[j]=ans[i+j]-'0';
		funtion(str);
	}
	printf("\n");
} 

int main(){
	int num;
	scanf("%d",&num);
	
	while(num--){
		init();
		head=DFS(0,0,N);
		print();
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章