又是一週數算實習,馬上就要上機考試了整個都要不好了,還好這一次的四分樹作業給了我一丟丟的信心…
作業是禁止使用STL的,而且明確要求必須用空間數據結構,所以這道題本來可以用廣搜寫的很簡單,但是爲了滿足作業需求我還是使用了四分樹,並且用數組模擬了隊列進行廣搜,直接用隊列廣搜會有更好的效果。
總體思路就是根據每個區塊的特點去建立一個四分樹,四分樹的每個結點就代表這一個區塊的特性,如果state1的值爲1,就意味着這個區塊裏面的數字既有1又有0,如果state1的值爲0,那麼這個區塊裏面所有的值都是一樣的,並且這個值記錄在state2裏面。
用遞歸的方法建樹,每次都判斷自己這個區塊是不是既有0又有1,如果是,那麼分成四塊繼續計算,如果不是,直接state1的值變爲0並且停止遞歸。
廣搜的時候用數組模擬了隊列,應該也沒什麼好多說的。在我的這個代碼中重複編碼的地方還是太多了,如果能把某個節點的四個指針放在一個指針數組裏面,這樣遍歷或者初始化的時候能夠方便很多,不過我也懶得修改了,就當提供一個思路。
再就是scan函數使用來前序遍歷整個樹來判斷樹有沒有寫對的,對整個程序沒有影響,在遍歷的時候我採用的是ACBD的順序遍歷結點,主要是因爲我定義的xy和題目中的反過來了= =
#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
#define maxn 520
bool map[maxn][maxn]={0};
bool output[4*maxn*maxn]={0};
int result[maxn]={0};
struct area{
int x1,y1,x2,y2;
};
struct node{
area a;
node *A, *B, *C, *D;
int state1;
int state2;
};
node* queue[4*maxn*maxn]={0};
void build(node* root){
bool one = 0, zero = 0;
area temp = root->a;
//cout<<"("<<temp.x1<<","<<temp.y1<<")"<<"("<<temp.x2<<","<<temp.y2<<")"<<endl;
for(int i=temp.x1;i<temp.x2;++i){
for(int j=temp.y1;j<temp.y2;++j){
if(map[i][j])
one = 1;
else
zero = 1;
if(one&&zero)
break;
}
if(one&&zero)
break;
}
if(one&&zero){
root->state1 = 1;
int midx = (temp.x1 + temp.x2)>>1;
int midy = (temp.y1 + temp.y2)>>1;
//printf("x1: %d x2: %d\n",temp.x1,temp.x2);
//printf("midx: %d midy: %d\n",midx,midy);
root->A = new node;
root->B = new node;
root->C = new node;
root->D = new node;
root->A->A = root->A->B = root->A->C = root->A->D = NULL;
root->B->A = root->B->B = root->B->C = root->B->D = NULL;
root->C->A = root->C->B = root->C->C = root->C->D = NULL;
root->D->A = root->D->B = root->D->C = root->D->D = NULL;
int x1 = temp.x1,x2 = temp.x2,y1 =temp.y1, y2 =temp.y2;
(root->A->a).x1 = x1; (root->A->a).y1 = y1; (root->A->a).x2 = midx; (root->A->a).y2 = midy;
build(root->A);
(root->B->a).x1 = midx; (root->B->a).y1 = y1; (root->B->a).x2 = x2; (root->B->a).y2 = midy;
build(root->B);
(root->C->a).x1 = x1; (root->C->a).y1 = midy; (root->C->a).x2 = midx; (root->C->a).y2 = y2;
build(root->C);
(root->D->a).x1 = midx; (root->D->a).y1 = midy; (root->D->a).x2 = x2; (root->D->a).y2 = y2;
build(root->D);
return;
}
else{
root->state1 = 0;
root->state2 = one;
}
return;
}
int BFS(node *root){
int start = 0,end = 0;
int ocount = 0;
queue[start] = root;
end++;
while(start<end){
//cout<<ocount<<endl;
node* temp = queue[start++];
if(temp->state1){
output[ocount++] = 1;
}
else{
output[ocount++] = 0;
output[ocount++] = temp->state2;
}
if(temp->A)
queue[end++] = temp->A;
if(temp->C)
queue[end++] = temp->C;
if(temp->B)
queue[end++] = temp->B;
if(temp->D)
queue[end++] = temp->D;
}
return ocount;
}
void scan(node* root){
if(!root)
return;
if(root->state1){
printf("(1) ");
}
else{
printf("(0,%d) ",root->state2);
}
scan(root->A);
scan(root->C);
scan(root->B);
scan(root->D);
return;
}
void trans(int n){
int overload = n%4;
int recount = 0;
int t = 0;
for(int i=overload - 1;i>=0;--i){
t += output[i]<<(overload-i-1);
}
result[recount++] = t;
int total = n/4;
//cout<<"total: "<<total<<endl;
for(int i=0;i<total;++i){
int start = overload + i*4;
/*for(int j=0;j<4;++j)
printf("%d ",output[j+overload]);
printf("\n");*/
int t = 0;
for(int j=0 ;j < 4;++j){
t+=output[j+start]<<(3-j);
}
result[recount++] = t;
}
for(int i=0;i<=total;++i)
printf("%X",result[i]);
printf("\n");
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(map,0,sizeof(map));
int n;
scanf("%d",&n);
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
scanf("%d",&map[i][j]);
}
}
node *root = new node;
(root->a).x1 = 0;
(root->a).y1 = 0;
(root->a).x2 = n;
(root->a).y2 = n;
root->state1 = root->state2 = 0;
root->A = root->B = root->C = root->D = NULL;
build(root);
int total = BFS(root);
trans(total);
}
//system("pause");
return 0;
}