算法题实战积累(3)——方块转换(C语言)

题目来源: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变量的作用。

相关推荐
小熳芋19 小时前
单词搜索- python-dfs&剪枝
算法·深度优先·剪枝
Xの哲學19 小时前
Linux SLAB分配器深度解剖
linux·服务器·网络·算法·边缘计算
bu_shuo19 小时前
MATLAB中的转置操作及其必要性
开发语言·算法·matlab
高洁0120 小时前
图神经网络初探(2)
人工智能·深度学习·算法·机器学习·transformer
爱装代码的小瓶子20 小时前
算法【c++】二叉树搜索树转换成排序双向链表
c++·算法·链表
思成Codes20 小时前
数据结构:基础线段树——线段树系列(提供模板)
数据结构·算法
JAY_LIN——821 小时前
C语言>字符 (strlen) | 字符串函数(strcpy、strcat)
c语言
虾..1 天前
Linux 简单日志程序
linux·运维·算法
Trent19851 天前
影楼精修-眼镜祛反光算法详解
图像处理·人工智能·算法·计算机视觉·aigc
蓝色汪洋1 天前
经典修路问题
开发语言·c++·算法