一. 题目
1.题目描述
一块 n×n 正方形的黑白瓦片的图案要被转换成新的正方形图案。
写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:1.转 90°:图案按顺时针转 90°。
2.转 180°:图案按顺时针转 180°。
3.转 270°:图案按顺时针转 270°。
4.反射:图案在水平方向翻转(以中央铅垂线为中心形成原图案的镜像)。
5.组合:图案在水平方向翻转,然后再按照 1∼3 之间的一种再次转换。
6.不改变:原图案不改变。
7.无效转换:无法用以上方法得到新图案。如果有多种可用的转换方法,请选择序号最小的那个。 只使用上述 7 个中的一个步骤来完成这次转换。
2.输入格式
第一行一个正整数 n。然后 n 行,每行 n 个字符,全部为 @ 或 -,表示初始的正方形。接下来 n 行,每行 n 个字符,全部为 @ 或 -,表示最终的正方形。
3.输出格式
单独的一行包括 1∼7 之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。
4.输入输出样例
输入 #1
3
@-@
---
@@-
@-@
@--
--@
输出 #1
1
5.说明/提示
【数据范围】
对于100% 的数据,1≤n≤10。
二. 解题过程
1.创建变量
//题目中1≤n≤10,定义行和列都为15的字符数组防止溢出。
char a[15][15] = { 0 };//输入中的表示初始的正方形
char b[15][15] = { 0 };//输入中的表示最终的正方形
char c[15][15] = { 0 };//过度的中间正方形
char d[15][15] = { 0 };//过度的中间正方形
char e[15][15] = { 0 };//过度的中间正方形
int n, i, j;
2.数据输入
cin >> n;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
cin >> a[i][j];
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
cin >> b[i][j];
3.输出判断
if (f1(a, b, c, n) == 1)
cout << "1";
else if (f2(a, b, c, d, n) == 1)
cout << "2";
else if (f3(a, b, c, d, n) == 1)
cout << "3";
else if (f4(a, b, c, n) == 1)
cout << "4";
else if (f5(a, b, c, d, e, n) == 1)
cout << "5";
else if (f6(a, b, n) == 1)
cout << "6";
else
cout << "7";
4子函数完成
0.比较函数
int campare(char a[15][15], char b[15][15], int n)//a数组和b数组比较
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (a[i][j] != b[i][j])//确保每个元素相同
return 0;//有不同就返回0
return 1;//全部相同返回1
}
1.转 90°
以4X4表格为例转 90°
顺时针转 90°前
行\列 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | 1 | 2 | 3 | 4 |
1 | 5 | 6 | 7 | 8 |
2 | 9 | 10 | 11 | 12 |
3 | 13 | 14 | 15 | 16 |
顺时针转 90°后
行\列 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | 13 | 9 | 5 | 1 |
1 | 14 | 10 | 6 | 2 |
2 | 15 | 11 | 7 | 3 |
3 | 16 | 12 | 8 | 4 |
不难发现顺时针转 90°是将第一列逆序写在第一行,第二列逆序写在第二行,第三列逆序写在第三行,第四列逆序写在第四行,因此我们可以把顺时针转 90°翻译:为将第N列逆序写在第N行。
int f1(char a[15][15], char b[15][15], char c[15][15], int n)//a为转前数组,b为比较数组,c为转后数组
{
int i, j, x = 0, y = 0;
for (j = 0; j < n; j++)
{
for (i = n - 1; i >= 0; i--)
c[x][y++] = a[i][j];
x++;
y = 0;
}
return campare(b, c, n);//b,c数组比较是否相同
}
2.转 180°
顺时针转 180°可理解为顺时针转两个90°
int f2(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
f1(a, b, d, n);//d为a顺时针转90°后
f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 180°后
return campare(b, c, n);//b,c数组比较是否相同
}
3.转 270°
顺时针转 270°可理解为顺时针转三个90°
int f3(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
f1(a, b, c, n);//c为a顺时针转90°后
f1(c, b, d, n);//d为c顺时针转90°后,即a顺时针转 180°后
f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 270°后
return campare(b, c, n);//b,c数组比较是否相同
}
4.反射
以4X4表格为例中央铅垂线为中心形成原图案的镜像
反射前
行\列 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | 1 | 2 | 3 | 4 |
1 | 5 | 6 | 7 | 8 |
2 | 9 | 10 | 11 | 12 |
3 | 13 | 14 | 15 | 16 |
反射后
行i\列j | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | 4 | 3 | 2 | 1 |
1 | 8 | 7 | 6 | 5 |
2 | 12 | 11 | 10 | 9 |
3 | 16 | 15 | 14 | 13 |
不难发现
c
[
j
]
[
n
−
i
−
1
]
=
a
[
i
]
[
j
]
c[j][n−i-1]=a[i][j]
c[j][n−i−1]=a[i][j]
int f4(char a[15][15], char b[15][15], char c[15][15], int n)//a为反射前数组,b为比较数组,c为反射后数组
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
c[i][n - j - 1] = a[i][j];
return campare(b, c, n);//b,c数组比较是否相同
}
5.组合
int f5(char a[15][15], char b[15][15], char c[15][15], char d[15][15], char e[15][15], int n)//a为组合前数组,b为比较数组,c为反射后数组,d为反射和转后数组,e为过度数组
{
f4(a, b, c, n);//将a反射为c
if (f1(c, b, d, n) || f2(c, b, d, e, n) || f3(c, b, d, e, n))
return 1;
return 0;
}
6.不改变
int f6(char a[15][15], char b[15][15], int n)
{
return campare(a, b, n);a,b数组比较是否相同
}
三. 完整代码
#include<iostream>
using namespace std;
int campare(char a[15][15], char b[15][15], int n)//a数组和b数组比较
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (a[i][j] != b[i][j])//确保每个元素相同
return 0;//有不同就返回0
return 1;//全部相同返回1
}
int f1(char a[15][15], char b[15][15], char c[15][15], int n)//a为转前数组,b为比较数组,c为转后数组
{
int i, j, x = 0, y = 0;
for (j = 0; j < n; j++)
{
for (i = n - 1; i >= 0; i--)
c[x][y++] = a[i][j];
x++;
y = 0;
}
return campare(b, c, n);//b,c数组比较是否相同
}
int f2(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
f1(a, b, d, n);//d为a顺时针转90°后
f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 180°后
return campare(b, c, n);//b,c数组比较是否相同
}
int f3(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
f1(a, b, c, n);//c为a顺时针转90°后
f1(c, b, d, n);//d为c顺时针转90°后,即a顺时针转 180°后
f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 270°后
return campare(b, c, n);//b,c数组比较是否相同
}
int f4(char a[15][15], char b[15][15], char c[15][15], int n)//a为反射前数组,b为比较数组,c为反射后数组
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
c[i][n - j - 1] = a[i][j];
return campare(b, c, n);//b,c数组比较是否相同
}
int f5(char a[15][15], char b[15][15], char c[15][15], char d[15][15], char e[15][15], int n)//a为组合前数组,b为比较数组,c为反射后数组,d为反射和转后数组,e为过度数组
{
f4(a, b, c, n);//将a反射为c
if (f1(c, b, d, n) || f2(c, b, d, e, n) || f3(c, b, d, e, n))
return 1;
return 0;
}
int f6(char a[15][15], char b[15][15], int n)
{
return campare(a, b, n);a,b数组比较是否相同
}
int main()
{
char a[15][15] = { 0 };//输入中的表示初始的正方形
char b[15][15] = { 0 };//输入中的表示最终的正方形
char c[15][15] = { 0 };//过度的中间正方形
char d[15][15] = { 0 };//过度的中间正方形
char e[15][15] = { 0 };//过度的中间正方形
int n, i, j;
cin >> n;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
cin >> a[i][j];
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
cin >> b[i][j];
if (f1(a, b, c, n) == 1)
cout << "1";
else if (f2(a, b, c, d, n) == 1)
cout << "2";
else if (f3(a, b, c, d, n) == 1)
cout << "3";
else if (f4(a, b, c, n) == 1)
cout << "4";
else if (f5(a, b, c, d, e, n) == 1)
cout << "5";
else if (f6(a, b, n) == 1)
cout << "6";
else
cout << "7";
return 0;
}