【有营养的算法笔记】巧解蛇形矩阵

news/2024/11/30 0:46:24/

👑作者主页:@进击的安度因
🏠学习社区:进击的安度因(个人社区)
📖专栏链接:有营养的算法笔记
✉️分类专栏:题解

文章目录

  • 一、题目描述
  • 二、思路讲解
  • 三、代码实现

一、题目描述

输入两个整数 nm ,输出一个 nm 列的矩阵,将数字 1n × m 按照回字蛇形填充至矩阵中。

具体矩阵形式可参考样例。

输入格式

输入共一行,包含两个整数 nm

输出格式

输出满足要求的矩阵。

矩阵占 n 行,每行包含 m 个空格隔开的整数。

数据范围

1 ≤ n, m ≤ 100

输入样例

3 3

输出样例

1 2 3
8 9 4
7 6 5

二、思路讲解

蛇形矩阵,就是将数字以 回字形 填充到 二维数组 中,比如这样:

image-20221213204831664

我们把 二维数组的行 看做 x轴二维数组的列 看做 y轴

结合数轴,我们其实可以发现蛇形矩阵填数的规律:从左上角第一个元素开始,先向右填,碰边;向下填,碰边;向左填,碰边;向上填,碰到已经填过的位置,退回原位;向右填 … 之后就是重复上面的规律来填充。

通过规律可以发现 蛇形矩阵 填数的其实是和 x, y 两个轴是息息相关的,我们将数据的坐标记为 (x, y)

  • 向右走:(x, y) --> (x, y + 1),纵坐标 + 1
  • 向下走:(x, y) --> (x + 1, y),横坐标 + 1
  • 向左走:(x, y) --> (x, y - 1),纵坐标 - 1
  • 向上走:(x, y) --> (x - 1, y),横坐标 - 1

而上面四种移动在 题目中的具体表现 就像下面这样:

  1. x 不动 - x = 0y 向右移 - y + 1
  2. y 不动 - y = 0x 向下移 - x + 1
  3. x 不动 - x = 0y 向左移 - y - 1
  4. y 不动 - y = 0x 向上移 - x - 1

所以 xy 的坐标变化就分别有 4 种。便可以把这些移动方式存入数组:dx[] = { 0, 1, 0, -1 }, dy[] = { 1, 0, -1, 0 }

从开始填数到填数完成需要改变很多次方向,那么什么情况需要改变填数方式?

  • 填数越过左边界
  • 填数越过右边界
  • 填数越过上边界
  • 填数越过下边界
  • 填数位置已有数据

第五点 是最需要注意的,其实后面大多都是第五种情况,前四种情况基本只会在 最外一圈 用到。

在里层 碰到填过的数据 就得 “回退并拐弯” ,以免覆盖填过的数据。

到这儿主题思路其实已经讲完了,下面再讲一下细节

如果坐标 xy “飙错位置” ,如何把它 “拉回正确位置” ?可以用 ab 变量分别记录当前坐标在移动后是否超出范围,重新调整 移动方法 ,实际上就是重新选取 dxdy 数组中 合适的元素 ,然后重新计算 ab ,将坐标 拉回来 ,做出正确调整,再将 ab 赋给 xy

下面我们看看代码怎么写。

三、代码实现

#include <iostream>using namespace std;const int N = 110;// 全局中定义数组,元素默认初始化为0
int q[N][N];int n, m;int main()
{cin >> n >> m;int dx[] = { 0, 1, 0, -1 }, dy[] = { 1, 0, -1, 0 };// 起始 x 和 y 在 (0, 0),并且 d 为 0,对应着 x 不动,y 往右走int x = 0, y = 0, d = 0;for (int i = 1; i <= n * m; i++){q[x][y] = i;// 计算 a, b 的下一个位置int a = x + dx[d], b = y + dy[d];// 判断是否超限// 这里 q[a][b] 其实有一层妙用,由于全局数组是被初始化 0 的,// 只要填过数,q[a][b] 就必定为真if (a < 0 || a >= n || b < 0 || b >= m || q[a][b]){// 移动到下一个位置,% 4 获取 [0, 3] 下标d = (d + 1) % 4;a = x + dx[d], b = y + dy[d];}// 将正确的 a b 赋给 x yx = a, y = b;}for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cout << q[i][j] << " ";}cout << endl;}return 0;
}

http://www.ppmy.cn/news/3281.html

相关文章

基于Android的二维码识别系统的研究 与实现

XXXX 本科生毕业设计(论文) 学院(系)&#xff1a; XX 专 业&#xff1a; XX 学 生&#xff1a; XX 指导教师&#xff1a; XX XX 完成日期 年 月 XXX本科生毕业设计&#xff08;论文&#xff09; 基于Android的二维码识别系统的研究 与实现 Research and Implementati…

Linux 的常用命令

前言 本篇博客给大家介绍一些常见的 Linux 命令 目录操作 pwd 查看当前工作目录 clear 清除屏幕 cd ~ 当前用户目录 cd / 根目录 cd - 上一次访问的目录 cd .. 上一级目录 其中清除屏幕的快捷键是: ctrl l ls 语法: ls 选项 目录或文件 功能: 对于目录来说…

如何解决 Redis 数据倾斜、热点等问题

大家好&#xff0c;我是Tom哥。 Redis 作为一门主流技术&#xff0c;应用场景非常多&#xff0c;很多大中小厂面试都列为重点考察内容 前几天有星球小伙伴学习时&#xff0c;遇到下面几个问题&#xff0c;来咨询 Tom哥 考虑到这些问题比较高频&#xff0c;工作中经常会遇到&…

树莓派通过RF443MHz收发控制家庭灯

背景&#xff1a;家中随意贴开关损坏(一种通过443MHz控制的远程开关)&#xff0c;且关灯后到卧室需要摸黑&#xff0c;萌生了搞远程控制灯的想法&#xff0c;因为有吃灰的树莓派&#xff0c;所以考虑了最低成本的方案&#xff0c;只需购买价值几元钱的443MHz收发模块即可。 一…

社群私域流量的用户消费路径是什么

针对于用户运营&#xff0c;现在的企业是比较纠结的&#xff0c;企业主要纠结的对象就是应该采用什么方式来进行用户运营&#xff0c;只有将用户运营做好&#xff0c;那么企业才能够达成自己的目的&#xff0c;一般针对于用户运营&#xff0c;基于当前的市场环境&#xff0c;企…

win10下CH340模块下载stc89c52程序

没想到读研究生了还有水课需要用上51单片机&#xff0c;本科的时候一直是用开发板烧录程序的&#xff0c;这次舍不得花钱买开发板只能瞎折腾了。 准备材料 1.ch340转接板&#xff0c;最普通的那种3~5块钱 2.买的是一个焊接好的小单片机系统 &#xff08;BB一句&#xff0c;这…

JUnit 测试框架

JUnit注解test 注解BeforeEach 注解BeforeAll AfterEachAfterAll断言assertEqualsassertNotEqualsassertTrue用例执行顺序测试套件指定类&#xff0c;添加到套件中并执行一次添加一个包的类参数化单参数多参数借助文件动态参数注解 test 注解 通过对方法加上 test 注解&#…

list模拟实现

文章目录list的介绍list和vector的对比**list和vector对于排序算法速度的比较****list和vector对于迭代器的比较****list的模拟实现****框架****节点****迭代器****普通迭代器-普通写法****const 迭代器-普通写法****迭代器-高级写法****链表结构****关于节点的析构****关于迭代…