算法 - 矩阵变化


题目:ACwing 1344. 转换

题目来源:https://www.acwing.com/problem/content/1346/

描述:

我们现在要将一个 N×N 大小的由黑白瓷砖构成的正方形图案转换为一个新的正方形图案。

共有 7 种转换方式如下:

90 度旋转:将图案顺时针旋转 90 度。
180 度旋转:将图案顺时针旋转 180 度。
270 度旋转:将图案顺时针旋转 270 度。
镜像:沿着图片的中间垂直线翻转图片,使其变为自身的镜像。
组合:先进行镜像转换,再按照 1∼3 中的一种方式进行转换。
不改变:保持原图案,不做任何改变。
无效转换:上述任何一种方式都无法得到新图案。
如果只允许使用上述方式中的一种进行图形转换,能否将原图案转换为新图案?

请你求出用哪种转换方式,可以得到新图案,输出这一方式的序号。

如果有多种方式可以满足条件,则输出序号较小的方式的序号。

当然,如果无法完成转换,只能输出方式 7 无效转换。

输入格式

第一行一个整数 N,表示正方形图案的大小。

接下来 N 行,每行包含 N 个字符(‘-’或‘@’),表示初始的正方形图案。

再接下来 N 行,每行包含 N 个字符(‘-’或‘@’),表示希望得到的新正方形图案。

输出格式

输出一个 1∼7 之间的整数,表示将原图案转换为新图案所使用的具体转换方式的序号。

数据范围
$1≤N≤10$

输入样例:

1
2
3
4
5
6
7
3
@-@
---
@@-
@-@
@--
--@

输出样例:

1
1

算法1:

该图形为正方形,所以该图形对称利用双指针就行。

1
2
3
for(int i = 0; i < n; i++)
for(int j = 0, k = n - 1; j < k; j++, k--)
swap(a[i][j], a[i][k]);

正方形的顺时针旋转可以为先以 $y = -x$ 翻转;在以正方形的重点进行翻转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <vector>

using namespace std;
typedef vector<string> VS;
int n;

void mirror(VS& a)
{
for(int i = 0; i < n; i++)
for(int j = 0, k = n - 1; j < k; j++, k--)
swap(a[i][j], a[i][k]);
}

void rotate(VS& a)
{
for(int i = 0; i < n; i++)
for(int j = 0; j < i; j++)
swap(a[i][j], a[j][i]);

mirror(a);
}

int check(VS& a, VS& b)
{
auto c = a; // 这里auto 为类型为VS,为复制一遍vector
for(int i = 1; i <= 3; i++)
{
rotate(c);
if (c == b) return i;
}
c = a;
mirror(c);
if (c == b) return 4;

for(int i = 1; i<= 3; i++)
{
rotate(c);
if (c == b) return 5;
}

if (a == b) return 6;
return 7;
}


int main()
{
VS a, b;
cin >> n;
string line;
for(int i = 0; i < n; i++) cin >> line, a.push_back(line);
for(int i = 0; i < n; i++) cin >> line, b.push_back(line);

cout << check(a, b) << endl;
return 0;
}