算法题实战积累(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 小时前
深度学习是如何收敛的?梯度下降算法原理详解
人工智能·深度学习·算法
长路归期无望5 小时前
C语言小白实现多功能计算器的艰难历程
c语言·开发语言·数据结构·笔记·学习·算法
MobotStone6 小时前
AI训练的悖论:为什么越追求准确率越会产生幻觉?
算法
口嗨农民工6 小时前
win10默认搜索APP和window设置控制命板
linux·服务器·c语言
怀旧,7 小时前
【C++】26. 智能指针
开发语言·c++·算法
Haooog7 小时前
654.最大二叉树(二叉树算法)
java·数据结构·算法·leetcode·二叉树
Swift社区7 小时前
LeetCode 392 判断子序列
算法·leetcode·职场和发展
芒果量化7 小时前
ML4T - 第7章第8节 利用LR预测股票价格走势Predicting stock price moves with Logistic Regression
算法·机器学习·线性回归
东方芷兰8 小时前
JavaWeb 课堂笔记 —— 20 SpringBootWeb案例 配置文件
java·开发语言·笔记·算法·log4j·intellij-idea·lua