算法题实战积累(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变量的作用。

相关推荐
逐步前行2 小时前
C标准库--C99--布尔型<stdbool.h>
c语言·开发语言
SunnyKriSmile2 小时前
C语言译码操作
c语言·算法·if语句·译码操作·switch语句
傻童:CPU2 小时前
C语言需要掌握的基础知识点之线性表
c语言·1024程序员节
小小小CTFER2 小时前
理论题] 2025 年 “技耀泉城” 海右技能人才大赛网络安全知识竞赛题目(二)
算法·安全·web安全
Heavy sea3 小时前
Linux串口应用编程
linux·c语言·1024程序员节
再睡一夏就好3 小时前
【C++闯关笔记】详解多态
c语言·c++·笔记·学习·语法·1024程序员节
断剑zou天涯4 小时前
【算法笔记】暴力递归尝试
java·笔记·算法
油泼辣子多加5 小时前
【实战】自然语言处理--长文本分类(1)DPCNN算法
算法·自然语言处理·分类
I'm a winner5 小时前
基于YOLO算法的医疗应用专题:第一章 计算机视觉与深度学习概述
算法·yolo·计算机视觉