usaco持续更新中。
nocow 友情翻译
Transformations 方块转换
目录[隐藏] |
描述
一块N x N(1<=N<=10)正方形的黑白瓦片的图案要被转换成新的正方形图案。写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:
1:转90度:图案按顺时针转90度。
2:转180度:图案按顺时针转180度。
3:转270度:图案按顺时针转270度。
4:反射:图案在水平方向翻转(以中央铅垂线为中心形成原图案的镜像)。
5:组合:图案在水平方向翻转,然后再按照1到3之间的一种再次转换。
6:不改变:原图案不改变。
7:无效转换:无法用以上方法得到新图案。
如果有多种可用的转换方法,请选择序号最小的那个。
只使用1--7中的一个步骤来完成这次转换。
格式
PROGRAM NAME: transform
INPUT FORMAT:
(file transform.in)
第一行: 单独的一个整数N。
第二行到第N+1行: N行每行N个字符(不是“@”就是“-”);这是转换前的正方形。
第N+2行到第2*N+1行: N行每行N个字符(不是“@”就是“-”);这是转换后的正方形。
OUTPUT FORMAT:
(file transform.out)
单独的一行包括1到7之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。
SAMPLE INPUT
3 @-@ --- @@- @-@ @-- --@
SAMPLE OUTPUT
1
分析:对于这道题而言,因为只有几种变幻方式,暴力枚举即可!
暴力代码,3kb长度,就是如此任性!(解释一下吧:看下面。)
/*
ID:jwb11931
LANG:C
TASK:transform
*/
#include<stdio.h>
int n,i,j,m,a[11][11],b[11][11],sb[11][11],flag,l;
char c;
int main(){
freopen("transform.in","r",stdin);
freopen("transform.out","w",stdout);
scanf("%d",&n);
for(i=1;i<=n;i++){getchar();
for(j=1;j<=n;j++){
scanf("%c",&c);
if(c=='@')a[i][j]=2;
else a[i][j]=1;
}
}
for(i=1;i<=n;i++){getchar();
for(j=1;j<=n;j++){
scanf("%c",&c);
if(c=='@')sb[i][j]=2;
else sb[i][j]=1;
}
}
for(m=1;m<=6;m++){
if(m==1){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
b[j][n-i+1]=a[i][j];
}
}
flag=1;
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[i][j]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
if(flag){
printf("1\n");
break;
}
}
if(m==2){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
b[n-i+1][n-j+1]=a[i][j];
}
}
flag=1;
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[i][j]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
if(flag){
printf("%d\n",m);
break;
}
}
if(m==3){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
b[n-j+1][i]=a[i][j];
}
}
flag=1;
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[i][j]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
if(flag){
printf("%d\n",m);
break;
}
}
if(m==4){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
b[i][n-j+1]=a[i][j];
}
}
flag=1;
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[i][j]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
if(flag){
printf("%d\n",m);
break;
}
}
if(m==5){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
b[i][n-j+1]=a[i][j];
}
}
for(l=1;l<=3;l++){
flag=1;
if(l==1){
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[j][n-i+1]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
}
if(l==2){
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[n-i+1][n-j+1]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
}
if(l==3){
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(b[n-j+1][i]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
}
if(flag){
break;
}
}
if(flag){
printf("5\n");
break;
}
}
if(m==6){
flag=1;
for(i=1;i<=n;i++){if(!flag)break;
for(j=1;j<=n;j++){
if(a[i][j]==sb[i][j])flag=1;
else {
flag=0;
break;
}
}
}
if(flag){
printf("6\n");
break;
}
}
}
if(flag==0)printf("7\n");
return 0;
}
nocow的解释:
设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。 (以上内容已经经过st验证)
st插一句:
m==1
b[j][n-i+1]=a[i][j];
m==2
b[n-i+1][n-j+1]=a[i][j];
m==3
b[n-j+1][i]=a[i][j];
m==4
b[i][n-j+1]=a[i][j];
求你给赞吧!3kb代码不好写啊!!!