蛇形方阵:从思路到代码的完整实现

0 阅读5分钟

在算法竞赛和日常编程练习中,蛇形方阵、螺旋矩阵、回形取数等 “矩阵路径填充” 类题目屡见不鲜。很多同学会陷入 “一题一解” 的误区,针对不同题目写不同逻辑,却忽略了这类问题的核心本质:按固定规则控制方向,在矩阵中完成有序遍历

今天,我们就提炼出解决这类问题的通性通法 —— 方向向量法,用一套核心逻辑,搞定所有矩阵路径填充类题目。蛇形方阵作为最经典的入门案例,将成为我们掌握这套方法的最佳载体。

一、核心原理:方向向量法的 “三板斧”

所有矩阵路径填充问题,都可以拆解为 “定义方向→预判下一步→边界 / 规则转向” 三个核心步骤,这就是方向向量法的 “三板斧”,适用于任意维度、任意遍历规则的矩阵路径问题。

矩阵中的移动方向,本质是横纵坐标的增量变化。无论题目要求顺时针、逆时针、“之” 字形,还是自定义路径,都可以用两个一维数组(方向向量)统一表示。

对于二维矩阵的四方向移动(最常见场景),我们将方向抽象为 “右、下、左、上”,对应的坐标增量如下:

  • 向右:横坐标 x 不变,纵坐标 y+1 → dx[0] = 0, dy[0] = 1
  • 向下:横坐标 x+1,纵坐标 y 不变 → dx[1] = 1, dy[1] = 0
  • 向左:横坐标 x 不变,纵坐标 y-1 → dx[2] = 0, dy[2] = -1
  • 向上:横坐标 x-1,纵坐标 y 不变 → dx[3] = -1, dy[3] = 0

通法总结:无论题目要求多少个方向(如八方向、自定义方向),只需按规则列出坐标增量,存入dxdy数组即可。

2. 第二板斧:预判先行,规避无效移动

矩阵遍历的关键是 **“先判断,再移动” ,而非 “先移动,再回退”。每一步填充前,先根据当前方向计算下一步的坐标 **,再判断该坐标是否符合规则。

通法总结:预判的核心是 “提前计算下一个位置”,避免出现越界、重复访问等无效移动,这是所有路径填充问题的通用逻辑。

3. 第三板斧:规则驱动,动态切换方向

当预判的下一步不合法(越界、已访问、违反题目规则)时,需要按题目要求切换方向。切换逻辑通过方向索引取模实现,保证方向循环切换。

通法总结:方向切换的本质是 “索引递增 + 取模”,pos = (pos + 1) % 方向总数,适用于所有循环方向的题目。

二、实战落地:用通法解决蛇形方阵问题

以经典的顺时针蛇形方阵为例,完整演示方向向量法的通性通法落地过程,代码可直接迁移至同类题目。

问题描述

给定正整数n,生成n×n矩阵,从(1,1)开始,顺时针螺旋填充1~n²的数字。

通法步骤拆解(完全遵循 “三板斧”)

步骤 1:定义核心变量(适配所有矩阵题)

  • 矩阵数组arr[N][N]:存储填充结果,需初始化为 0(标记 “未访问”)。
  • 方向向量dx[4]、dy[4]:表示四方向增量。
  • 遍历变量:x, y(当前坐标)、cnt(填充数值)、pos(当前方向索引)。

步骤 2:执行填充循环(核心通法逻辑)

循环条件:填充数值cnt ≤ n²(遍历完成)。循环内执行 “填充→预判→转向→移动” 四步,完全复用通法逻辑。

步骤 3:格式化输出

按行遍历矩阵,格式化打印,保证输出美观。

#include<bits/stdc++.h>
using namespace std;

const int N=15;

int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int arr[N][N];


int main(){

    int n;
    cin>>n;
    int x=1,y=1;
    int cnt=1;
    int pos=0;
    while(cnt<=n*n)
    {
        arr[x][y]=cnt;
        int a=x+dx[pos],b=y+dy[pos];
        if(a<1||a>n||b<1||b>n||arr[a][b]!=0){
            pos=(pos+1)%4;
            a=x+dx[pos];
            b=y+dy[pos];
        }
        x=a;y=b;
        cnt++;

    }
    for (int i = 1; i <=n; i++)
    {
        for (int j = 1; j <=n; j++)
        {
            printf("%3d ",arr[i][j]);
        }
        cout<<endl;
        
    }
    

    
    return 0;
}

三、通法迁移:一招搞定所有变体问题

掌握方向向量法后,无需重写逻辑,只需修改方向向量合法性判断规则,即可解决所有矩阵路径填充变体,真正实现 “一通百通”。

变体 1:逆时针蛇形方阵

仅需修改方向向量顺序,将 “右、下、左、上” 改为 “右、上、左、下”:

int dx[4] = {0, -1, 0, 1}; // 右、上、左、下 int dy[4] = {1, 0, -1, 0};

变体 2:回形取数(从外圈到内圈,按行读取)

仅需修改合法性判断规则,将 “未访问” 改为 “已访问”,填充逻辑改为 “读取数值”,核心遍历框架完全不变。

变体 3:“之” 字形矩阵填充

仅需修改方向切换规则,当到达矩阵右边界时,方向改为 “向下 + 向左”,到达左边界时改为 “向下 + 向右”,方向向量和核心循环仍复用通法。

四、通法避坑指南(通用)

  1. 坐标索引统一:要么全程使用1-based(如本文),要么全程0-based,避免混合使用导致越界。
  2. 初始化必须到位:矩阵的 “访问标记”(如本文的 0)必须初始化,否则垃圾值会导致合法性判断失效。
  3. 最后一步保护:填充到最后一个数值时,无需更新坐标,避免转向后越界(通法:if (cnt < 总数量) 才移动)。
  4. 方向与规则匹配:方向向量的顺序,必须和 “转向逻辑” 严格对应,否则会出现遍历路径错误。

总结

矩阵路径填充类题目,看似千变万化,实则万变不离其宗。方向向量法通过 “抽象方向→预判下一步→规则转向” 的通性逻辑,将所有此类问题转化为同一套模板。