微軟筆試題 《Image Encryption》(最小表示法)

題目:

描述

A fancy square image encryption algorithm works as follow:

0. consider the image as an N x N matrix

1. choose an integer k∈ {0, 1, 2, 3}

2. rotate the square image k * 90 degree clockwise

3. if N is odd stop the encryption process

4. if N is even split the image into four equal sub-squares whose length is N / 2 and encrypt them recursively starting from step 0

Apparently different choices of the k serie result in different encrypted images. Given two images A and B, your task is to find out whether it is POSSIBLE that B is encrypted from A. B is possibly encrypted from A if there is a choice of k serie that encrypt A into B.

輸入

Input may contains multiple testcases.

The first line of the input contains an integer T(1 <= T <= 10) which is the number of testcases.

The first line of each testcase is an integer N, the length of the side of the images A and B.

The following N lines each contain N integers, indicating the image A.

The next following N lines each contain N integers, indicating the image B.

For 20% of the data, 1 <= n <= 15

For 100% of the data, 1 <= n <= 100, 0 <= Aij, Bij <= 100000000

輸出

For each testcase output Yes or No according to whether it is possible that B is encrypted from A.

樣例輸入
3
2
1 2
3 4
3 1
4 2
2
1 2
4 3
3 1
4 2
4
4 1 2 3
1 2 3 4
2 3 4 1
3 4 1 2
3 4 4 1
2 3 1 2
1 4 4 3
2 1 3 2
樣例輸出
Yes
No
Yes

思路:

題解:hihocoder

自我理解:

        利用等價類的思想,由於等價關係具備傳遞性,所以去判斷A和B 是否可以通過變換轉換爲相同的樣子。

        而這個相同的樣子,叫做最小表示,就是將等價類裏的元素進行排序,其中最小的那個就是最小表示。

        那麼問題來了,怎麼求最小表示了?

        在本題中如果將矩陣分割爲一些小矩陣,從左到右,從上到下,將這些小矩陣轉化爲最小表示,那麼整體不就是最小表示了,所以採用了遞歸的思想。


#include<iostream>
#include<cstring>
using namespace std;
#define MAX 107
struct M{
	int a[MAX][MAX],n;
	M(int n=0):n(n){
//		a=new int*[n];
//		for(int i=0;i<n;++i)
//		    a[i]=new int[n];
	}
//	~M(){
//		for(int i=0;i<n;++i)
//		    delete[] a[i];
//		delete[] a;
//	}
};

//比較 A<B?1:0 ; 
bool cmp(M& A,M& B,int s1,int e1,int s2,int e2){
	for(int i=s1;i<e1;++i)
	    for(int j=s2;j<e2;++j)
	    	if(A.a[i][j]<B.a[i][j])return true;
	    	else if(A.a[i][j]>B.a[i][j])return false;
	return false;
}

//對指定部分旋轉90度 
void rotate(M& m,int s1,int e1,int s2,int e2){
	M t(m.n);	        
	for(int i=0;i<e1-s1;++i)
	    for(int j=0;j<e2-s2;++j)
            t.a[s1+i][s2+j]=m.a[e1-1-j][s2+i];
	for(int i=s1;i<e1;++i)
	    for(int j=s2;j<e2;++j)
            m.a[i][j]=t.a[i][j];
}

//對指定部分分爲4塊,將這4塊旋轉90度 
void rotate_M(M& a,int s1,int e1,int s2,int e2){
	M t(a.n);
	int m=(e1-s1)/2;
	for(int i=s1;i<e1;++i)
	    for(int j=s2;j<e2;++j)
	        t.a[i][j]=a.a[i][j];
	        //left_top 
	for(int i=s1;i<e1-m;++i)
	    for(int j=s2;j<e2-m;++j)
	        t.a[i][j]=a.a[i+m][j];
	        //right_top
	for(int i=s1;i<e1-m;++i)
	    for(int j=s2+m;j<e2;++j)
	        t.a[i][j]=a.a[i][j-m];
	        //left_botton
	for(int i=s1+m;i<e1;++i)
	    for(int j=s2;j<e2-m;++j)
	        t.a[i][j]=a.a[i][j+m];
	        //right_botton
	for(int i=s1+m;i<e1;++i)
	    for(int j=s2+m;j<e2;++j)
	        t.a[i][j]=a.a[i-m][j];
	for(int i=s1;i<e1;++i)
	    for(int j=s2;j<e2;++j)
	        a.a[i][j]=t.a[i][j];
}

void dfs(M& a,int s1,int e1,int s2,int e2){
	M A(a.n);
	if((e1-s1)&1){
        A=a;
		for(int k=1;k<4;++k){
			rotate(A,s1,e1,s2,e2);
			if(cmp(A,a,s1,e1,s2,e2)){
                 a=A;
			}
		}
	}else{
		//left_top
		dfs(a,s1,(s1+e1)/2,s2,(s2+e2)/2);
        //right_top
		dfs(a,s1,(s1+e1)/2,(s2+e2)/2,e2);
		//left_botton
		dfs(a,(s1+e1)/2,e1,s2,(s2+e2)/2);
		//right_botton
		dfs(a,(s1+e1)/2,e1,(s2+e2)/2,e2);
        A=a;
		for(int k=1;k<4;++k){
			rotate_M(A,s1,e1,s2,e2);
			if(cmp(A,a,s1,e1,s2,e2)){
				for(int i=s1;i<e1;++i)
				    for(int j=s2;j<e2;++j)
				        a=A;
			}
		}		
	}
} 

int main(){
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		M a(n),b(n);
		for(int i=0;i<n;++i)
		    for(int j=0;j<n;++j)
		        cin>>a.a[i][j];
		for(int i=0;i<n;++i)
		    for(int j=0;j<n;++j)
		        cin>>b.a[i][j];
		        
		dfs(a,0,n,0,n);
		dfs(b,0,n,0,n);
		bool flag=true;
		for(int i=0;i<n&&flag;++i)
		    for(int j=0;j<n;++j)
			    if(a.a[i][j]!=b.a[i][j]){
			    	flag=false;
			    	break;
			    }
		if(flag)cout<<"Yes"<<endl;
		else cout<<"No"<<endl;        
	}
	return 0;
}


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