Section 1.2-Transformations
分析
设a是原始状态,b是改变后的状态。
水平翻转:
b[i,n-j+1]:=a[i,j]
右旋90度:
b[j,n-i+1]:=a[i,j]
枚举方案就行了,或直接枚举变换。
需要注意的是,USACO是不给用GOTO的。注意代码的清晰程度。
小提示:如果你觉得自己写的程序是对的,但是总是不能AC,那么,试着将它的各个功能分解成一个个子例程, 并逐个验证其正确性,就能迅速发现BUG在哪里。
其实有一个非常不错但是不容易想到的方法:假设读入的字符串是a,可以进行如下操作: 1.将a放入a1的左上角,做水平方向对称,放在a1的右上角。 2.将以上得到的a1的上一半做垂直方向对称,放在a1的下一半。 3.将a1的左上、左下、右上、右下各部分分别做中心对称(可以将整个部分行列互换),存在a2中。 进行以上操作后a2的右上角是#1,a1的右下角是#2,a2的左下角是#3,a1的右上角是#4,a2的右下角、a1的左下角、a2的左上角是#5,a1的左上角是#6。将a分别与八部分进行比较,与哪部分相同就返回那部分对应的值,如果没有则返回7。 (以上内容已经经过验证)
注意
1.在判断5的时候要注意一定是要有一个转换的过程,不能直接在没有中间数组的情况下套公式进行判断,这样可能会造成错误。 2.即使两组图形完全一样,不必经过转换,也必须先试验1-5的转换方法,如果都不行才能输出6,因为题目要求输出编号较小的转换方法
/* ID:pekingt1 PROG:transform LANG:C++ */ #include<iostream> #include<cstdio> #include<string.h> #include<cstdlib> #include<math.h> #include<algorithm> using namespace std; const int maxn=10+5; char mappre[maxn][maxn],mapnext[maxn][maxn]; int step=7; int N; void Init() { cin>>N; for(int i=0;i<N;i++) cin>>mappre[i]; for(int i=0;i<N;i++) cin>>mapnext[i]; return; } void Comp(int x) { int flag=1; for(int i=0;i<N;i++) for(int j=0;j<N;j++) if(mappre[i][j]!=mapnext[i][j]) flag=0; if(flag) if(x<step) step=x; } void DegRot90() { char temp[maxn][maxn]; for(int i=0;i<N;i++) for(int j=0;j<N;j++) temp[j][N-1-i]=mappre[i][j]; for(int i=0;i<N;i++) for(int j=0;j<N;j++) mappre[i][j]=temp[i][j]; } void Ref() { char temp[maxn][maxn]; for(int i=0;i<N;i++) for(int j=0;j<N;j++) temp[i][N-1-j]=mappre[i][j]; for(int i=0;i<N;i++) for(int j=0;j<N;j++) mappre[i][j]=temp[i][j]; } void Solve() { Comp(6); DegRot90(); Comp(1); DegRot90(); Comp(2); DegRot90(); Comp(3); DegRot90(); Ref(); Comp(4); for(int i=1;i<=3;i++) { DegRot90(); Comp(5); } cout<<step<<endl; } int main() { freopen("transform.in","r",stdin); freopen("transform.out","w",stdout); Init(); Solve(); return 0; }