AcWing 5379. 旋转和翻转

给定两个 N×N的由字符 XO 构成的字符矩阵。

你可以对第一个矩阵进行任意次(也可以不进行)旋转和翻转操作。

请你判断,能否通过旋转和翻转操作将第一个矩阵变为第二个矩阵。

旋转操作指将矩阵逆时针旋转 90,180,270度。翻转操作指将矩阵沿水平轴或垂直轴翻转。

输入格式

第一行包含整数 N。

接下来 N行,每行包含 N个字符,每个字符要么为 X,要么为 O,表示第一个矩阵。

接下来 N行,每行包含 N个字符,每个字符要么为 X,要么为 O,表示第二个矩阵。

输出格式

如果能够通过旋转和翻转操作将第一个矩阵变为第二个矩阵,则输出 Yes,否则输出 No

数据范围

前 4个测试点满足 1≤N≤4。所有测试点满足 1≤N≤10。

输入样例1:
4
XOOO
XXOO
OOOO
XXXX
XOOO
XOOO
XOXO
XOXX
输出样例1:
Yes
输入样例2:
2
XX
OO
XO
OX
输出样例2:
No

八数码棋盘的方格数为 9,字符种数也为 9,则棋盘的状态数最多等于 9 个数的排列 A99=9!<109。而本题方格数最多 100,字符种数为 2,若字符 X 的个数为 m,则棋盘的状态数等于从 100 个方格选 m 个放 X,剩余方格放 O 的方案数 Cm100。当 m=10

时,有

C10100=100×99×98×97×⋯×9110×9×8×7×⋯×1>100×99×88×77×⋯×1110×9×8×7×⋯×1=10×119>109

因此,枚举棋盘的所有状态会超时

分析:(本质一共8中情况)

#include <bits/stdc++.h>  // 引入C++标准库,包括常用的头文件
using namespace std;  // 使用标准命名空间

int n;  // 定义一个整型变量n,表示矩阵的大小
vector<string> a, b;  // 定义两个字符串向量a和b,用于存储输入的两个矩阵

// 定义一个函数flip,用于左右翻转矩阵
vector<string> flip(vector<string> a)
{
    for (int i = 0; i < n; i++)
        for (int j = 0, k = n - 1; j < k; j++, k--)
            swap(a[i][j], a[i][k]);
    return a;
}

// 定义一个函数rotate,用于逆时针旋转矩阵90度
vector<string> rotate(vector<string> a)
{
    a = flip(a);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            swap(a[i][j], a[j][i]);
    return a;
}

// 定义一个函数check,用于检查两个矩阵是否可以通过旋转和翻转变得相同
bool check()
{
    for (int i = 0; i < 4; i++)
    {
        a = rotate(a);
        if (a == b) return true;
    }

    a = flip(a);

    for (int i = 0; i < 4; i++)
    {
        a = rotate(a);
        if (a == b) return true;
    }

    return false;
}

int main()
{
    cin >> n;  // 从标准输入读取矩阵的大小n
    a = b = vector<string>(n);  // 初始化两个矩阵a和b,大小为n
    for (int i = 0; i < n; i++) cin >> a[i];  // 从标准输入读取矩阵a的元素
    for (int i = 0; i < n; i++) cin >> b[i];  // 从标准输入读取矩阵b的元素

    if (check()) cout << "Yes" << endl;  // 如果两个矩阵可以通过旋转和翻转变得相同,输出"Yes"
    else cout << "No" << endl;  // 否则输出"No"

    return 0;  // 程序结束,返回0
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值