【深基5.习6】蛇形方阵

GitHub跳转原题关系图返回列表

用方向数组按右、下、左、上的顺序行走,遇到边界或已填格就右转。

OJ: luogu

题目 ID: P5731

难度:入门

标签:模拟矩阵python

日期: 2026-07-15 18:54

题意

给出 n,输出一个 n * n 的蛇形方阵。从左上角填 1 开始,按顺时针方向填完整个矩阵。每个数字占 3 个字符宽度。

思路

用二维列表 matrix 保存方阵,未填的位置为 0

蛇形填数的方向顺序固定为:

text
右 -> 下 -> 左 -> 上

所以准备方向数组:

text
[(0, 1), (1, 0), (0, -1), (-1, 0)]

每填完一个数,先尝试沿当前方向走到下一格。如果下一格越界,或者已经填过数,就把方向右转一格,再计算下一格。

最后输出矩阵时,每个数字用 f"{value:3d}" 保证宽度为 3

这题是矩阵模拟和格式化输出练习,不创建 brute.py

Python 知识

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/oj_input_output_cheatsheet.md:二维矩阵可以用列表推导式创建。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:用 "".join(...) 拼接一整行输出。
  • directions[direction] 用下标选择当前方向。
  • direction = (direction + 1) % 4 表示按顺时针右转。
  • f"{value:3d}" 表示整数右对齐,占 3 个字符宽度。

代码

python
n = int(input())

matrix = [[0 for _ in range(n)] for _ in range(n)]
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]

row = 0
col = 0
direction = 0

for value in range(1, n * n + 1):
    matrix[row][col] = value

    dr, dc = directions[direction]
    next_row = row + dr
    next_col = col + dc

    if not (0 <= next_row < n and 0 <= next_col < n) or matrix[next_row][next_col] != 0:
        direction = (direction + 1) % 4
        dr, dc = directions[direction]
        next_row = row + dr
        next_col = col + dc

    row, col = next_row, next_col

for line in matrix:
    print("".join(f"{value:3d}" for value in line))
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */

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

int a[15][15]; // 蛇形方阵
int n;

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

int main() {
    cin >> n;
    int x = 1, y = 1, dir = 0;
    for (int v = 1; v <= n * n; v++) {
        a[x][y] = v;
        // 尝试沿当前方向走下一步
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        // 如果越界或已填数,右转方向
        if (nx < 1 || nx > n || ny < 1 || ny > n || a[nx][ny] != 0) {
            dir = (dir + 1) % 4;
            nx = x + dx[dir];
            ny = y + dy[dir];
        }
        x = nx;
        y = ny;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++)
            printf("%3d", a[i][j]);
        printf("\n");
    }
    return 0;
}

Pythonic 写法

方向数组蛇形:

python
n=int(input())
g=[[0]*n for _ in range(n)]
dirs=[(0,1),(1,0),(0,-1),(-1,0)]
r=c=d=0
for v in range(1,n*n+1):
    g[r][c]=v
    nr,nc=r+dirs[d][0],c+dirs[d][1]
    if not (0<=nr<n and 0<=nc<n) or g[nr][nc]:
        d=(d+1)%4
        nr,nc=r+dirs[d][0],c+dirs[d][1]
    r,c=nr,nc
for row in g:
    print(''.join(f'{x:3d}' for x in row))

复杂度

每个格子填一次,时间复杂度是 O(n2)O(n^2),矩阵空间复杂度是 O(n2)O(n^2)

总结

蛇形矩阵的关键是“尝试前进,不能走就右转”。用方向数组可以避免写四段重复逻辑。