方块转换

GitHub跳转原题关系图返回列表

用旋转原语与行反转原语复合出全部 8 种候选图案,按序号从小到大与目标逐表比较,取第一个匹配的序号。

OJ: roj

题目 ID: 2005

难度:入门

标签:模拟

创建: 2026-10-01 02:26

更新: 2026-10-06 09:21

题目描述

给定两个 N×NN \times N(N≤10N \le 10)黑白方阵 src 与 dst,判定 src 经 #1 旋转 90°、#2 旋转 180°、#3 旋转 270°、#4 水平翻转、#5 翻转后再旋转、#6 不变中哪种变成 dst,输出最小序号,无法得到输出 7。

思路

旋转 90°((r,c)→(c,N−1−r)(r,c)\to(c,N-1-r))与水平翻转两个原语复合出全部 8 个候选图案,按序号从小到大比对 dst,首个一致的序号即答案,全不匹配输出 7。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 02:26
# update_at: 2026-10-01 02:26


def rotate_cw(g: list[str]) -> list[str]:
    """顺时针旋转 90°:把原图行倒序后按列拼接(新图第 r 行 = 原图第 r 列自下而上)。"""
    return [''.join(row) for row in zip(*g[::-1])]


def solve() -> None:
    it = iter(sys.stdin.buffer.read().split())
    n = int(next(it))
    src = [next(it).decode() for _ in range(n)]   # 转换前图案
    dst = [next(it).decode() for _ in range(n)]   # 转换后图案

    r90, r180, r270 = rotate_cw(src), rotate_cw(rotate_cw(src)), rotate_cw(rotate_cw(rotate_cw(src)))
    mirror = [row[::-1] for row in src]  # #4:水平翻转(每行倒序)
    m90, m180, m270 = (rotate_cw(mirror), rotate_cw(rotate_cw(mirror)),
                       rotate_cw(rotate_cw(rotate_cw(mirror))))  # #5 的三种组合

    # 按序号从小到大列出全部候选,序号 5 对应三种"翻转后再旋转"
    candidates = ((1, r90), (2, r180), (3, r270), (4, mirror),
                  (5, m90), (5, m180), (5, m270), (6, src))
    print(next((no for no, pat in candidates if pat == dst), 7))


if __name__ == "__main__":
    import sys
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-06 09:17
 * update_at: 2026-10-06 09:17
 */

#include <iostream>
using namespace std;

typedef long long ll;

const int MAXN = 15;

char src[MAXN][MAXN];
char dst[MAXN][MAXN];
char tmp[MAXN][MAXN];
char buf[MAXN][MAXN];
int n;

// 将 g 顺时针旋转 90° 存入 res
void rotate_cw(char g[MAXN][MAXN], char res[MAXN][MAXN]) {
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            res[j][n - 1 - i] = g[i][j];
}

// 将 g 水平翻转存入 res
void mirror(char g[MAXN][MAXN], char res[MAXN][MAXN]) {
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            res[i][n - 1 - j] = g[i][j];
}

// 比较两个图案是否完全相同
bool same(char a[MAXN][MAXN], char b[MAXN][MAXN]) {
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (a[i][j] != b[i][j])
                return false;
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> src[i][j];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> dst[i][j];

    // 候选图案:#1 旋转90°,#2 旋转180°,#3 旋转270°,#4 水平翻转,
    // #5 翻转后再旋转90°/180°/270°,#6 原样
    char r90[MAXN][MAXN], r180[MAXN][MAXN], r270[MAXN][MAXN];
    char mir[MAXN][MAXN], m90[MAXN][MAXN], m180[MAXN][MAXN], m270[MAXN][MAXN];

    rotate_cw(src, r90);
    rotate_cw(r90, r180);
    rotate_cw(r180, r270);
    mirror(src, mir);
    rotate_cw(mir, m90);
    rotate_cw(m90, m180);
    rotate_cw(m180, m270);

    if (same(r90, dst))  { cout << 1 << '\n'; return 0; }
    if (same(r180, dst)) { cout << 2 << '\n'; return 0; }
    if (same(r270, dst)) { cout << 3 << '\n'; return 0; }
    if (same(mir, dst))  { cout << 4 << '\n'; return 0; }
    if (same(m90, dst))  { cout << 5 << '\n'; return 0; }
    if (same(m180, dst)) { cout << 5 << '\n'; return 0; }
    if (same(m270, dst)) { cout << 5 << '\n'; return 0; }
    if (same(src, dst))  { cout << 6 << '\n'; return 0; }
    cout << 7 << '\n';
    return 0;
}