Skip to content

喵~ 各位Master,大家好呀!今天由本喵来给大家讲解一道非常可爱的题目哦,一起来看看吧!(ฅ'ω'ฅ)

A. Beautiful Matrix


题目大意

想象一下,我们有一个 5x5 的小方格,就像一个棋盘一样,喵~。这个方格里有24个0和一个孤零零的1。我们的任务呀,就是把这个1移动到最中间的位置,也就是第3行第3列。

我们可以做的操作有两种:

  1. 交换相邻的两行。
  2. 交换相邻的两列。

问题是:最少需要多少次交换,才能让矩阵变得“漂亮”(也就是让1跑到最中心)呢?


解题思路

这道题看起来好像要考虑复杂的交换顺序,但其实想通了就非常简单啦,喵~

  1. 找到'1'的位置:首先,我们得先找到那个1到底藏在哪里了,对不对?就像找躲起来的小鱼干一样!我们可以用两个循环,一个走遍所有行(从1到5),一个走遍所有列(从1到5),把整个矩阵搜一遍,就能找到1的坐标 (r, c) 啦。

  2. 独立移动:这是最关键的一步哦,Master请听好!移动行和移动列是互不干扰的!也就是说,我们把1上下移动(交换行)的时候,它的左右位置(列)是不会变的;同理,左右移动(交换列)的时候,它的上下位置(行)也不会变。这就像猫猫我呀,跳到高处和在地板上跑来跑去是两回事的说~

  3. 计算步数

    • 既然行和列的移动是独立的,我们就可以分开计算。
    • 要把1从第 r 行移动到目标第 3 行,需要多少步呢?因为每次只能和相邻的行交换,所以移动 k 行的距离,就需要 k 次交换。那么,行方向需要的步数就是 |r - 3|
    • 同理,要把1从第 c 列移动到目标第 3 列,需要的步数就是 |c - 3|
  4. 最终答案:所以呀,总的最小步数,就是行方向的移动步数 加上 列方向的移动步数。这就是一个很有名的概念,叫做“曼哈顿距离”,喵~

最终的公式就是:总步数 = |r - 3| + |c - 3|

是不是超级简单呢?我们只需要找到1的位置,然后代入公式算一下就得到答案啦!


题解

下面是具体的实现代码,本喵给加上了可爱的注释哦~

cpp
#include <iostream>
#include <cmath> // 引入 cmath 库来使用 abs() 函数,用来取绝对值喵

// 这道题的目标是把一个 5x5 矩阵里唯一的 '1' 移动到中心 (3, 3)
// 移动方式是交换相邻的行或列
//
// 核心思想是:行移动和列移动是独立的!
// 把 '1' 从第 r 行移动到第 3 行,最少需要 |r - 3| 次行交换
// 把 '1' 从第 c 列移动到第 3 列,最少需要 |c - 3| 次列交换
// 总的最小步数就是两者之和,也就是曼哈顿距离
//
// 算法步骤:
// 1. 遍历矩阵,找到 '1' 的坐标 (r, c)
// 2. 计算 |r - 3| + |c - 3|
// 3. 输出结果,搞定收工,喵~

int main() {
    // 让输入输出快一点,虽然这题数据量很小,但好习惯要保持嘛~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int row_of_one = 0; // 用来记录 '1' 所在的行
    int col_of_one = 0; // 用来记录 '1' 所在的列

    // 题目说行和列是从 1 到 5 编号的,我们就按这个来循环,方便计算
    for (int i = 1; i <= 5; ++i) {
        for (int j = 1; j <= 5; ++j) {
            int element;
            std::cin >> element; // 读入一个数字
            if (element == 1) {
                // 找到'1'啦!赶紧记下它的位置!
                row_of_one = i;
                col_of_one = j;
                // 因为只有一个'1',找到后其实可以不用再读了,
                // 但为了简单,就让循环跑完吧~
            }
        }
    }

    // 目标中心位置是第 3 行,第 3 列
    const int target_row = 3;
    const int target_col = 3;

    // 使用 abs() 函数计算曼哈顿距离
    int moves = std::abs(row_of_one - target_row) + std::abs(col_of_one - target_col);

    // 输出最终答案!用 '\n' 换行会比 std::endl 快一点点哦
    std::cout << moves << '\n';

    return 0; // 程序完美结束~
}

知识点介绍

这道题虽然简单,但背后有一些很有用的知识点呢!

  1. 曼哈顿距离 (Manhattan Distance)

    • 这个名字听起来很酷吧!想象一下你在纽约曼哈顿这样的城市里,街道都是横平竖直的网格状。你从一个路口走到另一个路口,不能斜着穿过大楼,只能沿着街道走。你走过的总路程,就是横向走的街区数加上纵向走的街区数。
    • 在二维坐标系中,点 (x1, y1)(x2, y2) 之间的曼哈顿距离就是 |x1 - x2| + |y1 - y2|
    • 这道题里,交换相邻行/列的操作,就和在网格里每次只能走一格是完全一样的道理,所以可以直接套用这个公式,喵~
  2. 二维数组/矩阵遍历 (2D Array/Matrix Traversal)

    • 用嵌套的for循环来访问矩阵里的每一个小格子,是处理矩阵问题的基本操作。外层循环控制行,内层循环控制列(或者反过来),这样就能不重不漏地访问所有元素啦。这是Master一定要掌握的基础技能哦!
  3. 问题分解 (Problem Decomposition)

    • 这是一个非常重要的编程思想!把一个看起来有点复杂的“移动”问题,分解成两个独立的、简单的“行移动”和“列移动”问题。分别解决后再把结果合并,问题一下子就清晰了。学会把大问题拆解成小问题,是成为编程高手的必经之路的说!

好啦,今天的讲解就到这里啦~ 是不是很简单易懂呢?Master下次也要继续努力哦,喵~(^・ω・^§)ノ

Released under the MIT License.