微软笔试题 《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;
}


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