USACO_CHA1_方块转换

一、题目描述

链接https://www.acwing.com/problem/content/1346/
来源:ACwing

我们现在要将一个 N×N 大小的由黑白瓷砖构成的正方形图案转换为一个新的正方形图案。

共有 7 种转换方式如下:

  1. 90 度旋转:将图案顺时针旋转 90 度。
  2. 180 度旋转:将图案顺时针旋转 180 度。
  3. 270 度旋转:将图案顺时针旋转 270 度。
  4. 镜像:沿着图片的中间垂直线翻转图片,使其变为自身的镜像。
  5. 组合:先进行镜像转换,再按照 1∼3 中的一种方式进行转换。
  6. 不改变:保持原图案,不做任何改变。
  7. 无效转换:上述任何一种方式都无法得到新图案。

如果只允许使用上述方式中的一种进行图形转换,能否将原图案转换为新图案?

请你求出用哪种转换方式,可以得到新图案,输出这一方式的序号。

如果有多种方式可以满足条件,则输出序号较小的方式的序号。

当然,如果无法完成转换,只能输出方式 7 无效转换。

输入格式
第一行一个整数 N,表示正方形图案的大小。

接下来 N 行,每行包含 N 个字符(‘-’或‘@’),表示初始的正方形图案。

再接下来 N 行,每行包含 N 个字符(‘-’或‘@’),表示希望得到的新正方形图案。

输出格式
输出一个 1∼7 之间的整数,表示将原图案转换为新图案所使用的具体转换方式的序号。

数据范围
1 ≤ N ≤ 10

输入样例

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

输出样例

1

二、题解

数据量较少的一道题,可以使用粗暴的解法。

即:找出各种转化的规律,然后将转化后的方形与目标方形比对。若相同则返回true,不同返回false。注意判断的时候要依据其所给顺序。

各种转化的规律:

初始
1 2 3
4 5 6
7 8 9

顺时针90度
7 4 1
8 5 2
9 6 3
第n列变第n行,行数变列数掉个个儿

顺时针180度
9 8 7
6 5 4
3 2 1
行掉个个儿,列也掉个个儿

顺时针270度
3 6 9
2 5 8
1 4 7
第n行到第n列,列数变行数掉个个儿

镜像
3 2 1
6 5 4
9 8 7
行不变,列掉个个儿

三、AC代码

#include<iostream>
using namespace std;
int n;
const int maxn = 15;
char Block[maxn][maxn];
char Target[maxn][maxn];
int op();
bool op1(char block[][maxn],char target[][maxn]);
bool op2(char block[][maxn],char target[][maxn]);
bool op3(char block[][maxn],char target[][maxn]);
bool op4(char block[][maxn],char target[][maxn]);
bool op5(char block[][maxn],char target[][maxn]);
bool op6(char block[][maxn],char target[][maxn]);
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> Block[i][j];
        }
    }
    
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> Target[i][j];
        }
    }
    
    cout << op() << endl;
    system("pause");
    return 0;
}

int op()
{
    if (op1(Block,Target))
    {
        return 1;
    }
    
    if (op2(Block,Target))
    {
        return 2;
    }

    if (op3(Block,Target))
    {
        return 3;
    }

    if (op4(Block,Target))
    {
        return 4;
    }

    if (op5(Block,Target))
    {
        return 5;
    }

    if (op6(Block,Target))
    {
        return 6;
    }

    return 7;
}

bool op1(char block[][maxn],char target[][maxn])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (block[i][j] != target[j][n - i - 1])
            {
                return false;
            }
        }
    }
    return true;
}

bool op2(char block[][maxn],char target[][maxn])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (block[i][j] != target[n - i - 1][n - j - 1])
            {
                return false;
            }
        }
    }
    return true;
}

bool op3(char block[][maxn],char target[][maxn])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (block[i][j] != target[n - j - 1][i])
            {
                return false;
            }
        }
    }
    return true;
}

bool op4(char block[][maxn],char target[][maxn])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (block[i][j] != target[i][n - j - 1])
            {
                return false;
            }
        }
    }
    return true;
}

bool op5(char block[][maxn],char target[][maxn])
{
    char Mirror[maxn][maxn];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            Mirror[i][n - j - 1] = block[i][j];
        }
    }

    if (op1(Mirror,Target))
    {
        return true;
    }
    
    if (op2(Mirror,Target))
    {
        return true;
    }

    if (op3(Mirror,Target))
    {
        return true;
    }

    return false;
}

bool op6(char block[][maxn],char target[][maxn])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (block[i][j] != target[i][j])
            {
                return false;
            }
        }
    }
    return true;
}

关于这道题,我的代码很容易理解,但是有些冗长。
转化的过程有的是可以省略掉的,比如90度,180度,270度,后者是前者转90度的结果,其实写一个90度旋转的函数就够用了。

如果我的题解对您有帮助,还望您不吝点赞。
欢迎讨论交流,期待共同进步!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值