hihoCoder #1240 : Image Encryption(最小表示法)

本文介绍了一种基于递归的图像加密算法,通过旋转和平分图像实现加密过程,并探讨了如何判断两个图像是否存在加密关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#1240 : Image Encryption

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

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 separately 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

   这道题可以用最小表示法去做,就是把两个矩阵都表示成其最小表示矩阵。判断它们的最小矩阵是否一样即可。我们可以定义最小表示矩阵:对于两个数字矩阵A,B,我们从上至下、从左至右逐个元素比较。若存在一个A(i,j)<B(i,j),则我们认为 A<B

例如下面两个例子,右边的数字矩阵就为边矩阵的最小表示:

3 1         1 4
2 4  ====>  3 2

3 1 3 2         1 2 1 2
2 4 1 4         4 3 3 4
2 4 1 2  ====>  1 3 1 4
1 3 4 3         4 2 3 2

    所以这道题的难点就转化成怎么表示其最小表示矩阵。我们可以通过dfs,将矩阵分割成最小(k*k,k为奇数),然后求该矩阵的最小表示。因为此时的矩阵
已经分割为最小,所以只用转3次然后取最小的即可。然后回溯上去。
还有一个要注意的地方,将矩阵分为4块,然后分别求出最小表示矩阵后,如

             A(1) | A(2)
matrix =      -----------
              A(4) | A(3)

此时这个矩阵由4个小矩阵构成,此时该矩阵的最小表示为下面四种的一种(而不是对这个矩阵进行旋转,然后取最小)

                                                                                                                                  A(4)|A(1)                        A(3)|A(4)                   A(2)|A(3)                       A(1)|A(2)       
matrix = -----------            matrix=   -----------        matrix=   ---------                 matrix= --------------           A(3)|A(2)                       A(2)|A(1)                   A(1)|A(4)                        A(4)|A(3)
                               
                                                                                                  

 

using namespace std;
int a[105][105],b[105][105];
int Min[105][105],now[105][105];
int temp[105][105];
void rotate(int t[105][105],int n,int starti,int startj)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            temp[i+starti][j+startj]=t[starti+n-1-j][startj+i];
        }
    }
     for(int i=starti;i<=n+starti-1;i++)
    {
        for(int j=startj;j<=n+startj-1;j++)
        {
            t[i][j]=temp[i][j];
        }
    }
}
bool cmp(int s[105][105],int x[105][105],int n,int starti,int startj)
{
    for(int i=starti;i<=n+starti-1;i++)
    {
        for(int j=startj;j<=n+startj-1;j++)
        {
            if(x[i][j]<s[i][j])
               return true;
			else if(x[i][j]>s[i][j])
			   return false;
        }
    }
    return false;
}
void matrix_rotate(int s[105][105],int n,int starti,int startj)
{
	int temp;
    for(int i=starti;i<=n/2+starti-1;i++)
    {
        for(int j=startj;j<=n/2+startj-1;j++)
        {
            temp=s[i][j];   
			s[i][j]=s[i][j+n/2];
			s[i][j+n/2]=temp;
        }
    }
	for(int i=starti;i<=n/2+starti-1;i++)
    {
        for(int j=startj+n/2;j<=n+startj-1;j++)
        {
            temp=s[i][j];   
			s[i][j]=s[i+n/2][j];
			s[i+n/2][j]=temp;
        }
    }
	for(int i=starti+n/2;i<=n+starti-1;i++)
    {
        for(int j=startj+n/2;j<=n+startj-1;j++)
        {
            temp=s[i][j];   
			s[i][j]=s[i][j-n/2];
			s[i][j-n/2]=temp;
        }
    }

}
void change(int x[105][105],int n,int starti,int startj)
{
    if(n%2!=0)
    {
        for(int i=starti;i<=n+starti-1;i++)
        {
            for(int j=startj;j<=n+startj-1;j++)
            {
                Min[i][j]=x[i][j];
                now[i][j]=x[i][j];
            }
        }
        for(int i=1;i<=3;i++)
        {
            rotate(now,n,starti,startj);
            if(cmp(Min,now,n,starti,startj))
            {
                for(int i=starti;i<=starti+n-1;i++)
                {
                    for(int j=startj;j<=n+startj-1;j++)
                    {
                        Min[i][j]=now[i][j];
                    }
                }
            }
        }
        for(int i=starti;i<=n+starti-1;i++)
        {
            for(int j=startj;j<=n+startj-1;j++)
            {
                x[i][j]=Min[i][j];
            }
        }
    }
    else
    {
        change(x,n/2,starti,startj);
        change(x,n/2,starti,startj+n/2);
        change(x,n/2,starti+n/2,startj);
        change(x,n/2,starti+n/2,startj+n/2);
        for(int i=starti;i<=n+starti-1;i++)
        {
            for(int j=startj;j<=n+startj-1;j++)
            {
                Min[i][j]=x[i][j];
                now[i][j]=x[i][j];
            }
        }
        for(int i=1;i<=3;i++)
        {
            matrix_rotate(now,n,starti,startj);
			if(cmp(Min,now,n,starti,startj))
			{
				for(int i=starti;i<=n+starti-1;i++)
				{
					for(int j=startj;j<=n+startj-1;j++)
					{
						Min[i][j]=now[i][j];
					}
				}
			}
        }
		
		for(int i=starti;i<=n+starti-1;i++)
	    {
		     for(int j=startj;j<=n+startj-1;j++)
			{
				x[i][j]=Min[i][j];
			}
		}
    }
}
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cin>>a[i][j];    
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cin>>b[i][j];    
            }
        }
        change(a,n,1,1);
		change(b,n,1,1);
		int flag=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(a[i][j]!=b[i][j])
				{
					flag=0;
					break;
				}
			}
		}
		if(flag==0)
		{
			cout<<"No"<<endl;
		}
		else
		{
			cout<<"Yes"<<endl;
		}
    }
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值