洛谷P1205[USACO1.2] 方块转换 Transformations 【C++题解】

一. 题目

1.题目描述

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

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

如果有多种可用的转换方法,请选择序号最小的那个。 只使用上述 7 个中的一个步骤来完成这次转换。

2.输入格式

第一行一个正整数 n。然后 n 行,每行 n 个字符,全部为 @ 或 -,表示初始的正方形。接下来 n 行,每行 n 个字符,全部为 @ 或 -,表示最终的正方形。

3.输出格式

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

4.输入输出样例

输入 #1

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

输出 #1

1

5.说明/提示

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

二. 解题过程

1.创建变量

//题目中1≤n≤10,定义行和列都为15的字符数组防止溢出。
char a[15][15] = { 0 };//输入中的表示初始的正方形
char b[15][15] = { 0 };//输入中的表示最终的正方形
char c[15][15] = { 0 };//过度的中间正方形
char d[15][15] = { 0 };//过度的中间正方形
char e[15][15] = { 0 };//过度的中间正方形
int n, i, j;

2.数据输入

cin >> n;
for (i = 0; i < n; i++)
	for (j = 0; j < n; j++)
		cin >> a[i][j];
for (i = 0; i < n; i++)
	for (j = 0; j < n; j++)
		cin >> b[i][j];

3.输出判断

if (f1(a, b, c, n) == 1)
	cout << "1";
else if (f2(a, b, c, d, n) == 1)
	cout << "2";
else if (f3(a, b, c, d, n) == 1)
	cout << "3";
else if (f4(a, b, c, n) == 1)
	cout << "4";
else if (f5(a, b, c, d, e, n) == 1)
	cout << "5";
else if (f6(a, b, n) == 1)
	cout << "6";
else
	cout << "7";

4子函数完成

0.比较函数

int campare(char a[15][15], char b[15][15], int n)//a数组和b数组比较
{
	int i, j;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			if (a[i][j] != b[i][j])//确保每个元素相同
				return 0;//有不同就返回0
	return 1;//全部相同返回1
}

1.转 90°

以4X4表格为例转 90°
顺时针转 90°前
行\列0123
01234
15678
29101112
313141516
顺时针转 90°后
行\列0123
013951
1141062
2151173
3161284

不难发现顺时针转 90°是将第一列逆序写在第一行,第二列逆序写在第二行,第三列逆序写在第三行,第四列逆序写在第四行,因此我们可以把顺时针转 90°翻译:为将第N列逆序写在第N行。

int f1(char a[15][15], char b[15][15], char c[15][15], int n)//a为转前数组,b为比较数组,c为转后数组
{
	int i, j, x = 0, y = 0;
	for (j = 0; j < n; j++)
	{
		for (i = n - 1; i >= 0; i--)
			c[x][y++] = a[i][j];
		x++;
		y = 0;
	}
	return campare(b, c, n);//b,c数组比较是否相同
}

2.转 180°

顺时针转 180°可理解为顺时针转两个90°

int f2(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
	f1(a, b, d, n);//d为a顺时针转90°后
	f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 180°后
	return campare(b, c, n);//b,c数组比较是否相同
}

3.转 270°

顺时针转 270°可理解为顺时针转三个90°

int f3(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
	f1(a, b, c, n);//c为a顺时针转90°后
	f1(c, b, d, n);//d为c顺时针转90°后,即a顺时针转 180°后
	f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 270°后
	return campare(b, c, n);//b,c数组比较是否相同
}

4.反射

以4X4表格为例中央铅垂线为中心形成原图案的镜像
反射前
行\列0123
01234
15678
29101112
313141516
反射后
行i\列j0123
04321
18765
21211109
316151413

不难发现
c [ j ] [ n − i − 1 ] = a [ i ] [ j ] c[j][n−i-1]=a[i][j] c[j][ni1]=a[i][j]

int f4(char a[15][15], char b[15][15], char c[15][15], int n)//a为反射前数组,b为比较数组,c为反射后数组
{
	int i, j;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			c[i][n - j - 1] = a[i][j];
	return campare(b, c, n);//b,c数组比较是否相同
}

5.组合

int f5(char a[15][15], char b[15][15], char c[15][15], char d[15][15], char e[15][15], int n)//a为组合前数组,b为比较数组,c为反射后数组,d为反射和转后数组,e为过度数组
{
	f4(a, b, c, n);//将a反射为c
	if (f1(c, b, d, n) || f2(c, b, d, e, n) || f3(c, b, d, e, n))
		return 1;
	return 0;
}

6.不改变

int f6(char a[15][15], char b[15][15], int n)
{
	return campare(a, b, n);a,b数组比较是否相同
}

三. 完整代码

#include<iostream>
using namespace std;
int campare(char a[15][15], char b[15][15], int n)//a数组和b数组比较
{
	int i, j;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			if (a[i][j] != b[i][j])//确保每个元素相同
				return 0;//有不同就返回0
	return 1;//全部相同返回1
}
int f1(char a[15][15], char b[15][15], char c[15][15], int n)//a为转前数组,b为比较数组,c为转后数组
{
	int i, j, x = 0, y = 0;
	for (j = 0; j < n; j++)
	{
		for (i = n - 1; i >= 0; i--)
			c[x][y++] = a[i][j];
		x++;
		y = 0;
	}
	return campare(b, c, n);//b,c数组比较是否相同
}
int f2(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
	f1(a, b, d, n);//d为a顺时针转90°后
	f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 180°后
	return campare(b, c, n);//b,c数组比较是否相同
}
int f3(char a[15][15], char b[15][15], char c[15][15], char d[15][15], int n)//a为转前数组,b为比较数组,c为转后数组,d为过度数组
{
	f1(a, b, c, n);//c为a顺时针转90°后
	f1(c, b, d, n);//d为c顺时针转90°后,即a顺时针转 180°后
	f1(d, b, c, n);//c为d顺时针转90°后,即a顺时针转 270°后
	return campare(b, c, n);//b,c数组比较是否相同
}
int f4(char a[15][15], char b[15][15], char c[15][15], int n)//a为反射前数组,b为比较数组,c为反射后数组
{
	int i, j;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			c[i][n - j - 1] = a[i][j];
	return campare(b, c, n);//b,c数组比较是否相同
}
int f5(char a[15][15], char b[15][15], char c[15][15], char d[15][15], char e[15][15], int n)//a为组合前数组,b为比较数组,c为反射后数组,d为反射和转后数组,e为过度数组
{
	f4(a, b, c, n);//将a反射为c
	if (f1(c, b, d, n) || f2(c, b, d, e, n) || f3(c, b, d, e, n))
		return 1;
	return 0;
}
int f6(char a[15][15], char b[15][15], int n)
{
	return campare(a, b, n);a,b数组比较是否相同
}
int main()
{
	char a[15][15] = { 0 };//输入中的表示初始的正方形
	char b[15][15] = { 0 };//输入中的表示最终的正方形
	char c[15][15] = { 0 };//过度的中间正方形
	char d[15][15] = { 0 };//过度的中间正方形
	char e[15][15] = { 0 };//过度的中间正方形
	int n, i, j;
	cin >> n;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			cin >> a[i][j];
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			cin >> b[i][j];
	if (f1(a, b, c, n) == 1)
		cout << "1";
	else if (f2(a, b, c, d, n) == 1)
		cout << "2";
	else if (f3(a, b, c, d, n) == 1)
		cout << "3";
	else if (f4(a, b, c, n) == 1)
		cout << "4";
	else if (f5(a, b, c, d, e, n) == 1)
		cout << "5";
	else if (f6(a, b, n) == 1)
		cout << "6";
	else
		cout << "7";
	return 0;
}
  • 43
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值