喵~ 各位Master,大家好呀!今天由本喵来给大家讲解一道非常可爱的题目哦,一起来看看吧!(ฅ'ω'ฅ)
A. Beautiful Matrix
题目大意
想象一下,我们有一个 5x5 的小方格,就像一个棋盘一样,喵~。这个方格里有24个0
和一个孤零零的1
。我们的任务呀,就是把这个1
移动到最中间的位置,也就是第3行第3列。
我们可以做的操作有两种:
- 交换相邻的两行。
- 交换相邻的两列。
问题是:最少需要多少次交换,才能让矩阵变得“漂亮”(也就是让1
跑到最中心)呢?
解题思路
这道题看起来好像要考虑复杂的交换顺序,但其实想通了就非常简单啦,喵~
找到'1'的位置:首先,我们得先找到那个
1
到底藏在哪里了,对不对?就像找躲起来的小鱼干一样!我们可以用两个循环,一个走遍所有行(从1到5),一个走遍所有列(从1到5),把整个矩阵搜一遍,就能找到1
的坐标(r, c)
啦。独立移动:这是最关键的一步哦,Master请听好!移动行和移动列是互不干扰的!也就是说,我们把
1
上下移动(交换行)的时候,它的左右位置(列)是不会变的;同理,左右移动(交换列)的时候,它的上下位置(行)也不会变。这就像猫猫我呀,跳到高处和在地板上跑来跑去是两回事的说~计算步数:
- 既然行和列的移动是独立的,我们就可以分开计算。
- 要把
1
从第r
行移动到目标第3
行,需要多少步呢?因为每次只能和相邻的行交换,所以移动k
行的距离,就需要k
次交换。那么,行方向需要的步数就是|r - 3|
。 - 同理,要把
1
从第c
列移动到目标第3
列,需要的步数就是|c - 3|
。
最终答案:所以呀,总的最小步数,就是行方向的移动步数 加上 列方向的移动步数。这就是一个很有名的概念,叫做“曼哈顿距离”,喵~
最终的公式就是:总步数 = |r - 3| + |c - 3|
。
是不是超级简单呢?我们只需要找到1
的位置,然后代入公式算一下就得到答案啦!
题解
下面是具体的实现代码,本喵给加上了可爱的注释哦~
#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; // 程序完美结束~
}
知识点介绍
这道题虽然简单,但背后有一些很有用的知识点呢!
曼哈顿距离 (Manhattan Distance)
- 这个名字听起来很酷吧!想象一下你在纽约曼哈顿这样的城市里,街道都是横平竖直的网格状。你从一个路口走到另一个路口,不能斜着穿过大楼,只能沿着街道走。你走过的总路程,就是横向走的街区数加上纵向走的街区数。
- 在二维坐标系中,点
(x1, y1)
和(x2, y2)
之间的曼哈顿距离就是|x1 - x2| + |y1 - y2|
。 - 这道题里,交换相邻行/列的操作,就和在网格里每次只能走一格是完全一样的道理,所以可以直接套用这个公式,喵~
二维数组/矩阵遍历 (2D Array/Matrix Traversal)
- 用嵌套的
for
循环来访问矩阵里的每一个小格子,是处理矩阵问题的基本操作。外层循环控制行,内层循环控制列(或者反过来),这样就能不重不漏地访问所有元素啦。这是Master一定要掌握的基础技能哦!
- 用嵌套的
问题分解 (Problem Decomposition)
- 这是一个非常重要的编程思想!把一个看起来有点复杂的“移动”问题,分解成两个独立的、简单的“行移动”和“列移动”问题。分别解决后再把结果合并,问题一下子就清晰了。学会把大问题拆解成小问题,是成为编程高手的必经之路的说!
好啦,今天的讲解就到这里啦~ 是不是很简单易懂呢?Master下次也要继续努力哦,喵~(^・ω・^§)ノ