P1205 [USACO1.2] 方块转换 Transformations

P1205 [USACO1.2] 方块转换 Transformations

题目描述

一块 n × n n \times n n×n 正方形的黑白瓦片的图案要被转换成新的正方形图案。写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:

  • 转 90 ° 90\degree 90°:图案按顺时针转 90 ° 90\degree 90°。

  • 转 180 ° 180\degree 180°:图案按顺时针转 180 ° 180\degree 180°。

  • 转 270 ° 270\degree 270°:图案按顺时针转 270 ° 270\degree 270°。

  • 反射:图案在水平方向翻转(以中央铅垂线为中心形成原图案的镜像)。

  • 组合:图案在水平方向翻转,然后再按照 1 ∼ 3 1 \sim 3 1∼3 之间的一种再次转换。

  • 不改变:原图案不改变。

  • 无效转换:无法用以上方法得到新图案。

如果有多种可用的转换方法,请选择序号最小的那个。

只使用上述 7 7 7 个中的一个步骤来完成这次转换。

输入格式

第一行一个正整数 n n n。

然后 n n n 行,每行 n n n 个字符,全部为 @-,表示初始的正方形。

接下来 n n n 行,每行 n n n 个字符,全部为 @-,表示最终的正方形。

输出格式

单独的一行包括 1 ∼ 7 1 \sim 7 1∼7 之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。

输入输出样例 #1

输入 #1

cpp 复制代码
3
@-@
---
@@-
@-@
@--
--@

输出 #1

cpp 复制代码
1

说明/提示

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 10 1\le n \le 10 1≤n≤10。

USACO Training Section 1.2

提交链接

Transformations

思路分析

📦 数据结构与变量说明

变量名 含义
s[19][19] 原始图案
t[19][19] 目标图案
temp[19][19] 存储变换后的图案用于比较

🔍 函数说明与实现解析


🔹 bool check(a, b)

  • 功能: 判断两个图案是否一模一样

🔹 bool change1(s) ------ 顺时针旋转 90°

  • 变换公式: temp[i][j] = s[n - 1 - j][i]

🔹 bool change2(s) ------ 顺时针旋转 180°

  • 变换公式: temp[i][j] = s[n - 1 - i][n - 1 - j]

🔹 bool change3(s) ------ 顺时针旋转 270°

  • 变换公式: temp[i][j] = s[j][n - 1 - i]

🔹 bool change4(s) ------ 水平反射

  • 变换公式: temp[i][j] = s[i][n - 1 - j]

🔹 组合变换(反射 + 旋转)

cpp 复制代码
char reflected[19][19];
for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
        reflected[i][j] = s[i][n - 1 - j];  // 先水平反射
        
然后尝试对反射后的图案再进行 90/180/270 度旋转,检查是否等于目标图。

🧩 主程序逻辑(流程图)

cpp 复制代码
读取 n 和两个图案 s、t
↓
尝试 change1(旋转 90°)→ 是 → 输出 1
↓
尝试 change2(旋转 180°)→ 是 → 输出 2
↓
尝试 change3(旋转 270°)→ 是 → 输出 3
↓
尝试 change4(反射)→ 是 → 输出 4
↓
尝试 反射+旋转组合 → 是 → 输出 5
↓
s 和 t 完全一致 → 是 → 输出 6
↓
否则 → 输出 7(无法变换)

完整代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

char s[19][19], t[19][19], temp[19][19];
int n;

bool check(char temp[][19], char t[][19]) // 判断两个 n * n 的图形是否一样
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (temp[i][j] != t[i][j])
                return false;
    return true;
}
bool change1(char s[][19]) /*翻转90度*/
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            temp[i][j] = s[n - 1 - j][i];

    return check(temp, t);
}
bool change2(char s[][19]) /*翻转180度*/
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            temp[i][j] = s[n - 1 - i][n - 1 - j];

    return check(temp, t);
}
bool change3(char s[][19]) /*翻转270度*/
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            temp[i][j] = s[j][n - 1 - i];
    return check(temp, t);
}
bool change4(char s[][19]) /*反射*/
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            temp[i][j] = s[i][n - 1 - j];
    return check(temp, t);
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) /*转换前*/
        cin >> s[i];

    for (int i = 0; i < n; i++) /*转换后*/
        cin >> t[i];

    if (change1(s)) // s 翻转 90 度后,看是否和 t 相等
    {
        cout << 1;
    }
    else if (change2(s)) // s 翻转 180 度后,看是否和 t 相等
    {
        cout << 2;
    }
    else if (change3(s)) // // s 翻转 270 度后,看是否和 t 相等
    {
        cout << 3;
    }
    else if (change4(s)) // 反射
    {
        cout << 4;
    }
    else // 组合
    {
        char reflected[19][19];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                reflected[i][j] = s[i][n - 1 - j];
        if (change1(reflected) || change2(reflected) || change3(reflected))
        {
            cout << 5;
        }
        else if (check(s, t))
        {
            cout << 6;
        }
        else
        {
            cout << 7;
        }
    }
    return 0;
}

官方思路

  • 数据结构
    用一个 Board 结构体保存图案内容;直接按值传递,可方便地返回新图案。
  • 三个基本操作
    • rotate:返回顺时针旋转 90° 后的棋盘
    • reflect:返回水平翻转后的棋盘
    • eqboard:判断两棋盘是否完全一致
  • 枚举判断顺序
    按 1→2→3→4→5→6→7 的顺序逐一比较,首次匹配即输出对应编号。

3️⃣ 代码逐行详解

cpp 复制代码
int n;              

struct Board {      
    char b[10][10];  
};

/* ---------- 旋转 90° ---------- */
Board rotate(Board x) {
    Board temp;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            temp.b[i][j] = x.b[n - 1 - j][i];
    return temp;
}

/* ---------- 水平翻转 ---------- */
Board reflect(Board x) {
    Board temp;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            temp.b[i][j] = x.b[i][n - 1 - j];
    return temp;
}

/* ---------- 判断两图是否相等 ---------- */
bool eqboard(Board x, Board y) {
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (x.b[i][j] != y.b[i][j])
                return false;
    return true;
}
cpp 复制代码
int main() 
{
    Board st, ed;
    cin >> n;

    /* 读入起始图案 */
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            cin >> st.b[i][j];

    /* 读入目标图案 */
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            cin >> ed.b[i][j];

    /* ---------- 按优先级逐一比较 ---------- */
    if (eqboard(ed, rotate(st)))                     cout << 1;
    else if (eqboard(ed, rotate(rotate(st))))        cout << 2;
    else if (eqboard(ed, rotate(rotate(rotate(st)))))cout << 3;
    else if (eqboard(ed, reflect(st)))               cout << 4;
    else if (eqboard(ed, rotate(reflect(st))) ||
             eqboard(ed, rotate(rotate(reflect(st)))) ||
             eqboard(ed, rotate(rotate(rotate(reflect(st)))))) cout << 5;
    else if (eqboard(ed, st))                        cout << 6;
    else                                             cout << 7;
    return 0;
}

判断逻辑说明:

  1. 编号 1 ∼ 3 1 \sim 3 1∼3:直接对 s t st st 连续调用 r o t a t e rotate rotate,分别比较 90 ° / 180 ° / 270 ° 90°/180°/270° 90°/180°/270°

  2. 编号 4 4 4:比较一次 r e f l e c t reflect reflect

  3. 编号 5 5 5: r e f l e c t reflect reflect 后再尝试三种旋转

  4. 写成三次 O R OR OR 判断最直观,也可使用循环减少代码

  5. 编号 6 6 6:若原图与目标图完全一致

  6. 编号 7 7 7:上述均不满足则输出 7 7 7

完整代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int n;

struct Board
{
    char b[10][10];
};

Board rotate(Board x) // 旋转90度
{
    Board temp;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            temp.b[i][j] = x.b[n - 1 - j][i];
    return temp;
}
Board reflect(Board x) // 水平旋转
{
    Board temp;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            temp.b[i][j] = x.b[i][n - 1 - j];
    return temp;
}
bool eqboard(Board x, Board y)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (x.b[i][j] != y.b[i][j])
                return false;
    return true;
}
int main()
{
    Board st, ed;
    cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> st.b[i][j];

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> ed.b[i][j];

    if (eqboard(ed, rotate(st)))
    {
        cout << 1;
    }
    else if (eqboard(ed, rotate(rotate(st))))
    {
        cout << 2;
    }
    else if (eqboard(ed, rotate(rotate(rotate(st)))))
    {
        cout << 3;
    }
    else if (eqboard(ed, reflect(st)))
    {
        cout << 4;
    }
    else if (eqboard(ed, rotate(reflect(st))) || eqboard(ed, rotate(rotate(reflect(st)))) || eqboard(ed, rotate(rotate(rotate(reflect(st))))))
    {
        cout << 5;
    }
    else if (eqboard(ed, st))
    {
        cout << 6;
    }
    else
    {
        cout << 7;
    }
    return 0;
}
相关推荐
2501_9248773525 分钟前
化工安防误报率↓82%!陌讯多模态融合算法实战解析
大数据·算法·目标跟踪·边缘计算
2501_9247474532 分钟前
强光干扰下误报率↓82%!陌讯多模态算法在睡岗检测的落地优化
人工智能·深度学习·算法·目标检测·计算机视觉
码破苍穹ovo43 分钟前
堆----3.数据流的中位数
java·数据结构·算法·力扣
Aousdu1 小时前
算法_python_学习记录_01
python·学习·算法
2501_927227441 小时前
密集遮挡场景识别率↑31%!陌讯轻量化部署方案在智慧零售的实战解析
人工智能·算法·目标检测·计算机视觉·目标跟踪·零售
武文斌7711 小时前
数据结构:哈希表、排序和查找
数据结构·散列表
金智维科技官方11 小时前
常见的大模型分类
人工智能·算法·ai·语言模型·数据挖掘
yzzzzzzzzzzzzzzzzz11 小时前
leetcode热题——有效的括号
算法·
崎岖Qiu12 小时前
leetcode1343:大小为K的子数组(定长滑动窗口)
java·算法·leetcode·力扣·滑动窗口
Shun_Tianyou12 小时前
Python Day25 进程与网络编程
开发语言·网络·数据结构·python·算法