#一、 思路
就是一步一步跟着走
#include <iostream>
using namespace std;
// 方向向量定义:4个方向的行/列偏移量(核心移动规则)
// p=0:右 (dx=0, dy=1) | p=1:左下 (dx=1, dy=-1)
// p=2:下 (dx=1, dy=0) | p=3:右上 (dx=-1, dy=1)
int dx[4] = { 0, 1, 1, -1 };
int dy[4] = { 1, -1, 0, 1 };
// 存储n阶蛇形矩阵,大小1001x1001可满足n≤1000的场景
int arr[1001][1001] = { 0 };
int main()
{
int n;
cin >> n; // 输入矩阵阶数(n×n)
int x = 0, y = 1; // 初始填充位置(从(0,1)开始填2,因为(0,0)先填了1)
int p = 1; // 初始移动方向:p=1(左下方向)
int i = 2; // 当前要填充的数字(从2开始,(0,0)=1已手动初始化)
arr[0][0] = 1; // 矩阵左上角(0,0)填充第一个数字1
// 循环填充:直到填满n×n个数字(i从2到n²)
while (i <= n * n)
{
arr[x][y] = i++; // 填充当前位置,然后数字i自增(准备填下一个)
// 核心逻辑1:分「前半段/后半段」切换方向规则
// 前半段(i < n²/2 + n/2):右→左下、下→右上
// 后半段(i ≥ 该值):右→右上、下→左下
if (i < n * n / 2 + n / 2)
{
if (p == 0) // 当前方向是右(p=0),切换为左下(p=1)
{
p = 1;
}
else if (p == 2) // 当前方向是下(p=2),切换为右上(p=3)
{
p = 3;
}
}
else // 后半段:切换规则改变
{
if (p == 0) // 当前方向是右(p=0),切换为右上(p=3)
{
p = 3;
}
else if (p == 2) // 当前方向是下(p=2),切换为左下(p=1)
{
p = 1;
}
}
// 计算当前方向p的下一个坐标(nx, ny)
int nx = x + dx[p];
int ny = y + dy[p];
// 核心逻辑2:边界检查与方向修正(越界时调整方向+重新计算坐标)
if (nx < 0 || nx >= n || ny < 0 || ny >= n)
{
// 按越界类型切换方向(优先级:行下界>列左界>列右界>行上界)
if (nx >= n) // 行越下界(nx≥n),切换为右(p=0)
{
p = 0;
}
else if (ny < 0) // 列越左界(ny<0),切换为下(p=2)
{
p = 2;
}
else if (ny >= n) // 列越右界(ny≥n),切换为下(p=2)
{
p = 2;
}
else if (nx < 0) // 行越上界(nx<0),切换为右(p=0)
{
p = 0;
}
// 切换方向后,重新计算新的坐标(基于新方向p)
nx = x + dx[p];
ny = y + dy[p];
}
// 更新当前坐标为新坐标(准备下一次填充)
x = nx;
y = ny;
}
// 输出填充后的n阶矩阵
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << arr[i][j] << " "; // 输出当前位置值,空格分隔
}
cout << '\n'; // 每行结束换行
}
return 0;
}



京公网安备 11010502036488号