P1205 [USACO1.2] 方块转换 Transformations

该文描述了一个编程问题,涉及将n×n的黑白瓦片图案通过旋转90°、180°、270°或水平反射来变换至目标图案。程序需找到最小转换步骤,如有多重方法则选择序号最小的操作。解决方案包括使用二维字符数组模拟转换过程并检查图案是否匹配。
摘要由CSDN通过智能技术生成

题目描述

一块 n × n n \times n n×n 正方形的黑白瓦片的图案要被转换成新的正方形图案。写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:

  1. 90 ° 90\degree 90°:图案按顺时针转 90 ° 90\degree 90°
  2. 180 ° 180\degree 180°:图案按顺时针转 180 ° 180\degree 180°
  3. 270 ° 270\degree 270°:图案按顺时针转 270 ° 270\degree 270°
  4. 反射:图案在水平方向翻转(以中央铅垂线为中心形成原图案的镜像)。
  5. 组合:图案在水平方向翻转,然后再按照 1 ∼ 3 1 \sim 3 13 之间的一种再次转换。
  6. 不改变:原图案不改变。
  7. 无效转换:无法用以上方法得到新图案。

如果有多种可用的转换方法,请选择序号最小的那个。

只使用上述 7 7 7 个中的一个步骤来完成这次转换。

输入格式

第一行一个正整数 n n n

然后 n n n 行,每行 n n n 个字符,全部为 @-,表示初始的正方形。

接下来 n n n 行,每行 n n n 个字符,全部为 @-,表示最终的正方形。

输出格式

单独的一行包括 1 ∼ 7 1 \sim 7 17 之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。

样例输入

3
@-@
---
@@-
@-@
@--
--@

样例输出

1

【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 10 1\le n \le 10 1n10

思路分析
本题就是用二维字符数组进行模拟。需要我们特别有耐心的解题。
顺时针旋转180°是2次顺时针旋转90°;顺时针旋转270°是3次顺时针旋转90°。所以,题目给的7个操作,可以被拆解成2个不同的操作:
a、顺时针旋转90°
b、反射
注意: 题目要求,有多种可用的转换方法时选择序号最小的那个。所以必须按1~7的操作顺序处理。
参考代码

#include <iostream>
#include <cstring> //memcpy(destination, source, num_bytes)
using namespace std;

const int N = 15;
char a[N][N],a1[N][N], b[N][N], t[N][N];
int n; //n一定要是全局变量,因为函数中要使用

//顺时针旋转90度
void rotate90() {
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			t[j][n - 1 - i] = a[i][j]; // 顺时钟旋转90°,结果存到数组t里
	memcpy(a, t, sizeof(t)); // 替换原来的 a

}
//反射
void reflex() {
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n / 2; j++)
			swap(a[i][n - 1 - j], a[i][j]); // 图案在水平方向翻转
}

//比较a和b是否相等
bool equal() {
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if (a[i][j] != b[i][j]) // 位置上某个字符不一样
				return false;
	return true; // 否则代表两个矩阵相等
}
//
int main() {
	//读入两个正方形图案
	cin >> n;
	//读入a
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> a[i][j];
	//读入b
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> b[i][j];
	//先将a拷贝一份,因为题目要求“有多种可用的转换方法时选择序号最小的那个”,所以必须按顺序处理。
	//前面处理的过程中会修改a,所以留个备份。
	memcpy(a1,a,sizeof(a));
	//判断
	rotate90();
	if (equal()) {// 顺时针旋转90°后相等
		cout << 1;
		return 0;
	}
	rotate90();
	if (equal()) {// 顺时针旋转180°后相等
		cout << 2;
		return 0;
	}
	rotate90();
	if (equal()) {//顺时针旋转270°后相等
		cout << 3;
		return 0;
	}
	memcpy(a,a1,sizeof(a)); //将a重置到初始状态
	reflex(); //反射
	if (equal()) {//反射后相等
		cout << 4;
		return 0;
	}
	//反射后,按1~3任一种旋转相等
	for (int i = 0; i < 3; i++) {
		rotate90();
		if (equal()) {
			cout << 5;
			return 0;
		}
	}
	memcpy(a,a1,sizeof(a)); //将a重置到初始状态
	if (equal()) { // 初始状态就相等
		cout << 6;
		return 0;
	}
	//无效转换
	cout << 7;
	return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值