洛谷P1205 [USACO1.2] 方块转换 Transformations

题目描述

[USACO1.2] 方块转换 Transformations

题目描述

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

  • 转 $90\degree$:图案按顺时针转 $90\degree$。

  • 转 $180\degree$:图案按顺时针转 $180\degree$。

  • 转 $270\degree$:图案按顺时针转 $270\degree$。

  • 反射:图案在水平方向翻转(以中央铅垂线为中心形成原图案的镜像)。

  • 组合:图案在水平方向翻转,然后再按照 $1 \sim 3$ 之间的一种再次转换。

  • 不改变:原图案不改变。

  • 无效转换:无法用以上方法得到新图案。

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

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

输入格式

第一行一个正整数 $n$。

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

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

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

1

提示

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

这是一道普及-的题目!!

卡了我好久,这道题目主要的坑就在“如果有多种可用的转换方法,请选择序号最小的那个。”这句话里。只旋转的优先级是最高的,就算两个图形一样也得转。

公式由推导可得(我觉得这道题主要的难点就在推导公式,但是由于本人太菜,讲不出前因后果,所以只把公式放出来)

(定义原数组为a,受体数组为b)

操作1:b[j][n-i+1]=a[i][j]

操作2:b[n-i+1][n-j+1]=a[i][j]

操作3:b[n-j+1][i]=a[i][j]

操作4:b[i][n-j+1]=a[i][j];

废话不多说,上代码。代码虽然很长但是整体结构还是比较清晰的

#include<bits/stdc++.h>
using namespace std;
int n;
bool a[15][15],b[15][15],c[15][15],d[15][15];
void move(){//这里是将受体 C数组的值备份到d数组,方便进行多次操作 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			d[i][j]=c[i][j];
		}
	}
}
void ope_1(){//操作1  
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			c[j][n-i+1]=d[i][j];
		}
	}
} 
void ope_2(){//2 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			c[n-i+1][n-j+1]=d[i][j];
		}
	}
}
void ope_3(){//3
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			c[n-j+1][i]=d[i][j];
		}
	}
}
void ope_4(){//4
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			c[i][n-j+1]=d[i][j];
		}
	}
}
bool check(){//检查操作完成之后的数组是否符合要求,方法就是一个一个对比过去 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(b[i][j]!=c[i][j]){
				return false;
			}
		}
	}
	return true;
}
int main(){
	char A;
	cin>>n;//输入,个人觉得用char很麻烦,鉴于只有两种字符,就用bool存,方便、省空间 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>A;
			if(A=='@')	a[i][j]=1;
			else a[i][j]=0;		
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>A;
			if(A=='@')	b[i][j]=1;
			else b[i][j]=0;		
		}
	}//为了方便后续操作,所有的“操作”函数中的受体均为c,母体均为d 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			d[i][j]=a[i][j];
		}
	}
	//开始进行只旋转的操作 
	ope_1();
	if(check()){
		cout<<"1";
		return 0;
	}
	ope_2();
	if(check()){
		cout<<"2";
		return 0;
	}
	ope_3;
	if(check()){
		cout<<"3";
		return 0;
	}
	//进行4操作,4操作可能与旋转构成一整个操作5
	//但是4的序号比5大所以优先级更高 
	ope_4();
	if(check()){
	 cout<<"4";//先处理只有4的操作 
	 return 0;
	}else{//开始处理4+旋转的操作 
		move();
		ope_1();
		if(check()){
			cout<<"5";
			return 0;
		}
		ope_2();
		if(check()){
			cout<<"5";
			return 0;
		}
		ope_3();
		if(check()){
			cout<<"5";
			return 0;
		}
	}
	bool flag=0;//开始处理不用操作的操作 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n,flag==0;j++){
			if(a[i][j]!=b[i][j]){
				flag=1;
				break;
			}
		}
	}
	if(flag==0){
		cout<<"6";
	}else
	cout<<"7";//剩下的只剩7了... 
	
}
posted @ 2022-07-03 23:56  YJCA  阅读(282)  评论(0)    收藏  举报