题解 P1205 【[USACO1.2]方块转换 Transformations】

· · 题解

大模拟!!!

说实话,我认为本题的算法并不是搜索,而是模拟,题目已经很明确的说了,n一共有7种情况,我们把这七种情况一个一个分情况讨论,答案就出来了。

\text{正式进入题目(咳咳,严肃)}

由于题目要求将每一次所变换的图形与原图形进行比较,所以定义数组a[15][15],b[15][15],c[15][15],d[15][15](\text{题目申明}1 \leq n\leq10),a数组表示第一个输入的矩阵,b数组表示变换后的矩阵,c数组表示要对照的矩阵,d数组为将要存放的矩阵,所以可以写出以下判断b矩阵与c矩阵相同的代码
↓↓↓

for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;

简单明了,蒟蒻都能懂!

First:n=1

设原矩阵为↓↓↓

11 12 13
21 22 23
31 32 33

那么,经过顺时针转90度的矩阵为

31 21 11
32 22 12
33 23 13

列出i(行)与j(列)的关系,如下:

再进行找规律,经推敲可得

b[j][n-i+1]=a[i][j]

再与前面所说的判断合在一起,可得:

bool work1()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        b[j][n-i+1]=a[i][j];
    }
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;
}
------------ $$Second:n=2$$ 相同的,设原矩阵为↓↓↓ ``` 11 12 13 21 22 23 31 32 33 ``` 那么,经过顺时针转$180$度的矩阵为 ``` 33 32 31 23 22 21 13 12 11 ``` 列出$i$(行)与$j$(列)的关系,如下: ![](https://cdn.luogu.com.cn/upload/pic/60017.png) 分析可得 $$b[n-i+1][n-j+1]=a[i][j]$$ 代码实现: ``` bool work2() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) b[n-i+1][n-j+1]=a[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=c[i][j]) return 0; return 1; } ``` 当然,当$n=2$时,也可以看做**进行了两次$1$操作**,即: ``` void work2() { work1(); //第一次操作 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=b[i][j]; //重置矩阵 work1(); //第二次操作 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=c[i][j]) return 0; return 1; } ``` 两代码的结果相同,但前者效率较高,后者代码短小精悍,更好理解。 $∴$当$n=2$时,代码打好了。 $$QAQ$$ ------------ $$Third:n=3$$ 同样的,设原矩阵为↓↓↓ ``` 11 12 13 21 22 23 31 32 33 ``` 那么,经过顺时针转$270$度的矩阵为 ``` 13 23 33 12 22 32 11 21 31 ``` 列表: ![](https://cdn.luogu.com.cn/upload/pic/60024.png) 这次规律有一些难找了,是 $$b[n-j+1][i]=a[i][j]$$ 于是 ``` bool work3() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) b[n-j+1][i]=a[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=c[i][j]) return 0; return 1; } ``` 也可以看作**先进行一次$1$操作再进行一次$2$操作** 代码: ``` bool work3() { work1(); //第一次操作 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=b[i][j]; //重置矩阵 work2(); //第二次操作 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=c[i][j]) return 0; return 1; } ``` $$n=3\text{完工!}$$ ------------ $$Fourth:n=4$$ 同样的,设原矩阵为↓↓↓ ``` 11 12 13 21 22 23 31 32 33 ``` 那么,经过反射的矩阵为 ``` 13 12 11 23 22 21 33 32 31 ``` ~~又是无聊的列表:~~ ![](https://cdn.luogu.com.cn/upload/pic/60025.png) 可以找出 $$b[i][n-j+1]=a[i][j]$$ 代码实现: ``` bool work4() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) b[i][n-j+1]=a[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=c[i][j]) return 0; return 1; } ``` $$OK$$ ------------ $$Fifth:n=5$$ $5$操作就是将$4,1,2,3$操作混和(~~粗略的说法~~),作者为了~~偷懒~~,$QAQ$,就~~不找规律~~了,给出代码: ``` bool work5() { work4(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=d[i][j]; //重置矩阵 if(work1()) return 1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=d[i][j]; //重置矩阵 if(work2()) return 1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=d[i][j]; //重置矩阵 if(work3()) return 1; return 0; } ``` $$\text{逃}$$ ------------ $$Sixth:n=6$$ 没有操作,直接比较: ``` bool work6() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=c[i][j]) return 0; return 1; } ``` $$easy$$ ------------ $$Seventh:n=7$$ 直接输出$7$即可 ``` cout<<7; ``` ------------ 核心代码已经打完了,我们可以将代码美观化,用一个$work$函数把它们包起来 ``` void work() { if(work1()) { cout<<1; return ; } if(work2()) { cout<<2; return ; } if(work3()) { cout<<3; return ; } if(work4()) { cout<<4; return ; } if(work5()) { cout<<5; return ; } if(work6()) { cout<<6; return ; } cout<<7; } ``` ------------ $My complete code
#include<bits/stdc++.h>
using namespace std;
int n;
char a[15][15],b[15][15],c[15][15],d[15][15];
bool work1()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        b[j][n-i+1]=a[i][j];
    }
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;
}
bool work2()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        b[n-i+1][n-j+1]=a[i][j];
    }
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;
}
bool work3()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        b[n-j+1][i]=a[i][j];
    }
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;
}
bool work4()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        b[i][n-j+1]=a[i][j];
    }
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;
}
bool work5()
{
    work4();
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      a[i][j]=b[i][j];  
      if(work1())
      return 1;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      a[i][j]=b[i][j]; 
      if(work2())
      return 1;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      a[i][j]=b[i][j]; 
      if(work3())
      return 1;
      return 0;
}
bool work6()
{
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
     if(b[i][j]!=c[i][j])
     return 0;
     return 1;
}
void work()
{
    if(work1())
    {
        cout<<1;
        return ;
    }
    if(work2())
    {
        cout<<2;
        return ;
    }
    if(work3())
    {
        cout<<3;
        return ;
    }
    if(work4())
    {
        cout<<4;
        return ;
    }
    if(work5())
    {
        cout<<5;
        return ;
    }
    if(work6())
    {
        cout<<6;
        return ;
    }
    cout<<7;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     {
        cin>>a[i][j];
        d[i][j]=a[i][j];
     }

    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      cin>>c[i][j];
    work();
    return 0; //完美的结束QAQ
}