【算法】小技巧之:矩阵偏移量(floodfill算法的铺垫)

整体算法思想来自:

【【寒假每日一题】Day-3(《 756. 蛇形矩阵》偏移量技巧)】 https://www.bilibili.com/video/BV1mK411M7Ng/?share_source=copy_web&vd_source=fe1ac3bec858ccd7b6481fa1ea1d9820

目录

偏移量法

如何定义dx、dy数组?

实例(图解)

模板

 实战(做题)

链接

题目


偏移量法

偏移量法的核心思想是使用两个数组来控制遍历方向。这种方法特别适合于遍历二维空间时的方向控制。

如何定义dx、dy数组?


矩阵遍历使用的x和y的定义有些特殊。

通常,在数学和计算机图形学中,我们习惯于将x轴定义为水平方向,y轴定义为垂直方向。然而,在二维数组或矩阵的上下文中,这些轴的定义通常与传统的笛卡尔坐标系有所不同。

  • 在代码中
  • x变量代表的是二维数组的行索引。
  • y变量代表的是二维数组的列索引。

然而,

  1. 当我们说“向上”移动时,实际上是在减少x的值(因为在数组中向上移动意味着向更小的行索引移动)。所以对应的坐标变为:(x-1 , y)
  2. 同样,"向右"移动实际上是增加y的值(在数组中向右移动意味着向更大的列索引移动)。所以对应的坐标变为:(x , y+1)
  3. “向下”移动是增加x的值。所以对应的坐标变为:(x+1 , y)
  4. “向左”移动是减少y的值。这种定义方式是基于二维数组的索引,其中matrix[x][y]表示位于第x行和第y列的元素。

所以,尽管这种定义方式可能与传统的笛卡尔坐标系不同,但它完全适合于二维数组或矩阵的遍历操作。

实例(图解)

 在这里给出一个例子:

列出针对(x,y)上下左右的偏移量数组

偏移量按照“上、右、下、左”的顺序来定义的。这个顺序决定了遍历矩阵的方向。

在代码中:

dx = {-1, 0, 1, 0} 表示行的变化。

dy = {0, 1, 0, -1} 表示列的变化。

这里的偏移量对应的遍历方向是:

  • 向上(dx = -1, dy = 0)。
  • 向右(dx = 0, dy = 1)。
  • 向下(dx = 1, dy = 0)。
  • 向左(dx = 0, dy = -1)。

在遍历过程中,通过改变d的值来选择不同的偏移量,从而改变遍历的方向。遍历始于向右方向(d = 1),并在遇到边界或已访问的元素时顺时针旋转到下一个方向。

这种方法特别适合处理这类二维数组遍历的问题。通过简单地调整偏移量数组,可以轻松地更改遍历的方向或模式,适应各种不同的需求和场景。

模板

偏移量法的核心在于定义一组方向向量,通过这些向量控制遍历的方向。这种方法的模板化可以分为以下几个步骤:

  1. 定义方向向量:创建两个数组,一个表示行的偏移(dx),另一个表示列的偏移(dy)。例如,对于上、右、下、左的顺时针方向,可以定义dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1}。
  2. 初始化遍历状态:设置起始点和初始方向,通常从(0,0)点开始,方向设置为向右。
  3. 遍历矩阵:使用一个循环进行遍历,每次移动后检查边界和是否已访问,必要时改变方向。
  4. 边界和访问状态检查:在每次移动后,检查下一个位置是否超出矩阵边界或者已经访问过。如果是,改变方向。

 实战(做题)

链接

756. 蛇形矩阵 - AcWing题库

题目

 


//acwing
//756.蛇形矩阵

//矩阵偏移量
//dx[4] ={-1,0,1,0}
//dy[4]={0,1,0,-1}
#include<iostream>
using namespace std;

const int N = 110;
int n, m;
int res[N][N];

int main()
{
	cin >> n >> m;
	//偏移量数组(上下左右方向)
	int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 };
	int dir = 1; //移动方向
	
	int x = 0, y = 0; //起始位置(0,0)
	for (int i = 1; i <= n * m; i++) //填充遍历
	{
		res[x][y] = i;//填充

		int a = x + dx[dir], b = y + dy[dir]; //使用临时变量,进行边界检查

		//边界检测----需要转向
		//在矩阵边缘-->转向
		//重复下标---> 转向

		//为什么会出现res[a][b]这个条件?
		//1.res[a][b] 检查重复下标
		//c++中,全局数组变量(非vector)的初始化默认是0。
		//而0可以被认为是false

		if (a < 0 || a >= n || b < 0 || b >= m || res[a][b]) //判断行走的下一个状态是否碰壁 
        //( 下移时是否碰越下界 || 右移时是否越右界  || 左移时是否越左界) || (若不改变移动方向 下一点是否已经到达过)
		{
			dir = (dir + 1) % 4;
			a = x + dx[dir], b = y + dy[dir];
		}
		x = a;
		y = b;
	}
	
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			cout << res[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

景鹤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值