蛇形填数我感觉好难但是

问题描述

作为一个一无所知的小白,我想像一个小孩子一样,先模仿,先跟着大神的思路和指导,抄抄代码,开始吧

蛇形填数。在n×n方阵里填入1,2,…,n×n,要求填成蛇形。例如,n=4时方阵为:

 10 11 12  1
  9 16 13  2
  8 15 14  3
  7  6  5  4

上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n≤8。

小白分析

我一开始也分析不出来什么,现在也是(废话一句)。直观的大家都看到了,还真的是像一条蛇一样,从外到内盘成一盘。待会结合刘汝佳大神的代码,咱们细说吧

刘汝佳大神说

类比数学中的矩阵,可以用一个二维数组来储存题目中的方阵。
【括号里是我说的:矩阵,大一还没学,但是入门一下还是可以的,自行百度,啥是矩阵。二维数组相当于一个变量跟有两个下标,类似坐标轴里的(x,y)这样才能表示二维世界里的东西,具体到一个数组如 array[x][y] ,这里的 x,y 就是这两个所谓的下标。】
只需声明一个 int a[maxn][maxm]; 就可以获得一个大小为 maxn x maxm 的方阵。
【不明白的地方,看下面的代码注释】
【这里想象成一支笔在画出这个矩阵图】
从 1 开始依次填写。设 ”笔“ 的坐标为(x,y),则一开始 x = 0, y = n - 1,即第 0 行,第 n - 1 列。”笔“的移动轨迹是:下,下,下,左,左,左,上,上,上,右,右,下,下,左,上。注意不能出界,也不能走到以前填过的格子。如果把所有格子都初始化为 0,就能很方便地加以判断。
【看来,只能从解读代码,注释代码来更好的理解了,我现在还是懵】

小白补充

个屁。好好学习吧,专注学习吧,专注AC,做点成绩,让学校赏口饭吃。(现在疫情期间,找个勤工俭学岗位,难难难……把宝贵的时间留给算法竞赛学习吧,在弹尽粮绝之前,突围 “算法竞赛入门”

代码注释

// 蛇形填数
/*
` 10 11 12  1
  9 16 13  2
  8 15 14  3
  7  6  5  4
*/

#include <stdio.h>
#include <string.h>
#define maxn 20
int a[maxn][maxn];

int main() {
    // 从后边的代码可以看到,tot 表示的是 "笔" 依次写出的 数字。
    int n, x, y, tot = 0; // tot 是 total 的缩写?表示总计。
    // 上边的 x,y 是二维数组的下标变量
    scanf("%d", &n); // 输入边长
    // 值初始化为 0
    memset(a, 0, sizeof(a)); // memset 的使用需要 #include <string.h>
    tot = a[x = 0][y = n - 1] = 1; // 从第 0 第 n - 1 个位置开始,并赋值为 1
    // 最外面的这个 while 控制的是整体上要执行到所有数字填完为止
    // 里边的几个 while 控制的是 每一圈的每个方向上的具体操作
    while(tot < n * n) // tot 最大为 n * n - 1
    {
        // 一开始先往下走,即 x 值依次增加,y 值不变
        // x + 1 表示的是将要被填入数字的项的 行坐标,也就是这里的第 x + 1 行
        // x + 1 首先不能越出这个矩阵边界,即,x + 1 < n
        // 且这个待填入数字的位置的值要为 0,即,这个位置还没填数字,反过来
        // 加上一个 !号,所对应的值就变为 1 了
        // 所以 while 的条件就是 x + 1 < n && !a[x + 1][y] 同时成立
        // 更进一步分析,就可以得出
        // 这支"笔", 像一个下在一样在“探路 ”,“探完路”后才会真正去决定要不要走
        // 边走边更新 ++x,++tot 的值(自增符++,注意这里是放在变量前边)
        while(x + 1 < n && !a[x + 1][y]) a[++x][y] = ++tot;
        // 下到底后(一开始是这样的),该向左转,此时只需要改变 y 的 值(依然判断是否符合 while 条件)
        while(y - 1 >= 0 && !a[x][y - 1]) a[x][--y] = ++tot;
        // 左到左后(不能再左了)(也是第一次的时候,可以左到头)
        // 上面那句话是用我自己的方言说的O.O
        // 通过改变 y 值(一点点减小),到达这一行的首位(第一次循环可以到达首位),还要满足此时的这个项的值为 0
        // 下,左,执行完,该上了
        while(x - 1 >= 0 && !a[x - 1][y]) a[--x][y] = ++tot;
        // 上的操作执行完,该往右了,只需要改变 y 的值
        while(y + 1 < n && !a[x][y + 1])  a[x][++y] = ++tot;
    }
    // 最外面的这个 while 控制的是整体上要执行到所有数字填完为止
    // 里边的几个 while 控制的是 每一圈的每个方向上的具体操作


    // 接下来该是简单的打印输出(按顺序输出即可)
    for(x = 0; x < n; x++) {
        for(y = 0; y < n; y++) printf("%3d", a[x][y]);
        printf("\n");
    }
    return 0;
}

闭上眼总结一下

喝了口茶。
二维数组
重点就是条件的编写,自己要推敲出来,什么时候执行下一个操作,执行下一个操作要满足什么条件。这里就是坐标值不能超过边界长,待填入的项必须是 0 (即,没有填过)。
还是先学习,模仿,夺取经,希望能少走点弯路。但是,很多时候,弯路又是必须的(绕了弯路,理解更深刻,这大概就是“慢就是快“的学习道理)。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值