题目来源:P1205 [USACO1.2] 方块转换 Transformations - 洛谷https://www.luogu.com.cn/problem/P1205

题目分析
本题中提到了旋转90°、旋转180°、旋转270°等方法来实现图案的变化,并且要求使用能完成转换的序号最小的方法,因此我们就要考虑到需要单独写出对应转换图案的功能代码,将这些功能分别包装成一个个函数,然后在主函数中依次调用,每次调用后判断是否与目标图案一致,一致则终止程序,若不一致则继续往下执行。这样不但实现了变化,也符合取最小序号的要求。
我们需要定义两个二维数组a、temp、b,分别保存原始数组、某方法转换后的临时数组和目标数组。注意这里有一个细节:这些数组的长度应该规定成题目说的最大值10,在遍历时再根据输入的n来限制次数即可。
在"组合"的方法中,还需要定义一个二维数组c,来保存水平镜像操作后的数组,再将c数组作为起始数组依次进行旋转变化,得到数组temp,再将temp与目标数组b比较是否相等。
代码实现
cs
#include <stdio.h>
//定义一个可以直接替换的变量
//#define 目标文本 目标文本的具体的内容
#define max 10
int n;
char a[max][max]; //起始数组
char b[max][max]; //目标数组
char temp[max][max]; //保存旋转处理的数据
//验证两个数组是否一致
// 1 表示true 0 表示false
int equal(char x[max][max], char y[max][max]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (x[i][j] != y[i][j]) {
return 0;
}
}
}
return 1;
}
//定义右转90°的函数
void rotate90(char src[max][max], char temp[max][max]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
temp[j][n - i - 1] = src[i][j];
}
}
}
void rotate180(char src[max][max], char temp[max][max]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
temp[n - i - 1][n - j - 1] = src[i][j];
}
}
}
void rotate270(char src[max][max], char temp[max][max]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
temp[j][n - i - 1] = src[i][j];
}
}
}
//水平镜像:左右对折
void refl(char src[max][max], char temp[max][max]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
temp[i][n - j - 1] = src[i][j];
}
}
}
int main() {
scanf("%d", &n);
//在数组中输入对应字符数据
for (int i = 0; i < n; i++) {
scanf("%s", a[i]);
}
for (int i = 0; i < n; i++) {
scanf("%s", b[i]);
}
//1.90°旋转
rotate90(a, temp);
if (equal(temp, b)) {
printf("1\n");
return 0;
}
//2.180°旋转
rotate180(a, temp);
if (equal(temp, b)) {
printf("2\n");
return 0;
}
//3.270°旋转
rotate270(a, temp);
if (equal(temp, b)) {
printf("3\n");
printArr(temp);
return 0;
}
//4.水平镜像
refl(a, temp);
if (equal(temp, b)) {
printf("4\n");
return 0;
}
//5.组合
char c[max][max];
refl(a, c);
//①90°旋转
rotate90(c, temp);
if (equal(temp, b)) {
printf("5\n");
return 0;
}
//②180°旋转
rotate180(c, temp);
if (equal(temp, b)) {
printf("5\n");
return 0;
}
//③270°旋转
rotate270(c, temp);
if (equal(temp, b)) {
printf("5\n");
return 0;
}
//6、直接相等
if (equal(a, b)) {
printf("6\n");
return 0;
}
//7、无法实现
printf("7\n");
return 0;
}
知识积累
1、二维数组存储矩阵数据
如上面的代码所示,我们只需要操作一维即可,因为二维数组本质上是一维数组的集合,存储着多个一维数组,操作一维即操作一行的二维数组,直接将相应的数据整体存入,更加方便。
2、数组各种变化的功能实现
首先明确:程序在执行嵌套循环时,会先将内层的循环执行完毕一次,外面的循环才实现数字递增一次。根据这个原理,我们在书写类似的数组变化时,可以在纸上举一些例子,看看原数组的数字都对应存到了新数组的那些位置,再寻找他们坐标之间的关系得出变化的规律,然后转换为代码的表示,这样就不容易导致混乱。
3、函数的书写及调用
和Java类似,C语言中的一个函数需要有返回值类型,函数名、参数、方法体。调用时可以直接在主函数中通过方法名并给定对应的参数进行调用(面向过程编程)。
4、#define的使用
#define 可以用于定义一个可以直接替换的变量(可以是任何类型),使用方法为:
#define 目标文本 目标文本的具体的内容 具体如上述代码所示
5、bool变量在C语言中的使用
在C语言中,bool变量不一定要直接使用这个类型,因为即使使用这个类型,程序给出的返回值也不是true或false,而是1或0。其中1代表true,0代表false。所以在上述代码书写判断数组是否一致的函数equal时,采用了int作为返回值类型,根据情况返回0或1,放到if语句的小括号内依然可以起到bool变量的作用。