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

相关推荐
robch15 分钟前
golang container/heap 是一个为任意类型实现堆(优先队列)接口的包
数据结构·算法·golang
967717 分钟前
力扣面试经典150 88. 合并两个有序数组 归并排序的merge函数
算法·leetcode·面试
放下华子我只抽RuiKe58 小时前
算法的试金石:模型训练、评估与调优的艺术
人工智能·深度学习·算法·机器学习·自然语言处理·数据挖掘·线性回归
oem1108 小时前
C++中的享元模式实战
开发语言·c++·算法
流云鹤8 小时前
每日一题0316
算法
leonkay8 小时前
Golang语言闭包完全指南
开发语言·数据结构·后端·算法·架构·golang
雅欣鱼子酱9 小时前
Type-C供电PD协议取电Sink芯片ECP5702,可二端头分开供电调整亮度,适用于LED灯带户外防水超亮灯条方案
c语言·开发语言
颜酱9 小时前
BFS 与并查集实战总结:从基础框架到刷题落地
javascript·后端·算法
casual~9 小时前
第?个质数(埃氏筛算法)
数据结构·c++·算法
仰泳的熊猫10 小时前
题目2308:蓝桥杯2019年第十届省赛真题-旋转
数据结构·c++·算法·蓝桥杯