蛇形填数

来源:互联网 发布:php与c进行socket通信 编辑:程序博客网 时间:2024/05/16 14:14

今天在Tyvj的初学者题库里面做到了Q1023 蛇形矩阵这一道题,找不到什么规律,就自己模拟蛇形移动,设计了下面这样一个算法,先贴代码,再做算法分析

//蛇形填数#include <iostream>using namespace std;int p[102][102];void display(int p[][102],int n){for(int i=1; i<=n; ++i){for(int j=1; j<n; ++j)cout << p[i][j] << ' ';cout << p[i][n] << endl;}}int main(){int n, t;cin >> n;int row=1, col=0, now=0, dir=4;while(p[row][col]!=n*n){if(dir==1){for(++row; row<=n; ++row){p[row][col] = ++now;if(p[row+1][col]!=0) break;}if(row>n) --row;}else if(dir==2){for(--col; col>=1; --col){p[row][col] = ++now;if(p[row][col-1]!=0) break;}if(col<1) ++col;}else if(dir==3){for(--row; row>=1; --row){p[row][col] = ++now;if(p[row-1][col]!=0) break;}if(row<1) ++row;}else{for(++col; col<=n; ++col){p[row][col] = ++now;if(p[row][col+1]!=0) break;}if(col>n) --col;}if(dir==4) dir = 1;else ++dir;}display(p,n);return 0;}

其实整个过程的思路很简单:

1)先把整个矩阵初始化为0(事实上,二维数组定义为全局变量,矩阵的所有元素就都初始化为0了。原因见第5)步),然后空出第0行和第0列空出来不要用来填数,即和常用的矩阵下标相对应,也为了后面的“越界判断”可行。

2)然后是确定填数的起点和方向,在上面,我是从左上角开始的,最初的方向是向右开始填数(dir即为direction,我这里当dir为1时,向下;dir为2时,向左;dir为3时,向上,dir为4时,向右,这些可以随自己定义的,只要自己觉得舒服直观就好)。

3)开始走了!每次走一步,关键在于判断什么时候拐弯,因为不拐弯的时候,只需要直走,把当前的值now赋给当前的位置就好了(我为了直观和方便,用row和col分别记录当前需要填充的位置的坐标)。

4)那么什么时候拐弯呢?抛开其他的限制,最多走n步就要拐弯了!这一点应该不用解释吧?然后其他情况呢?以上面代码描述的动作为例来讲,一开始向右走,dir=4,为什么第一次循环开始之前要++col呢?这个的意思是向右横跨一步,因为可以看成上一次是向上走的,走到了尽头,那么下一次就要拐弯向右走,所以得先向右跨一步,再继续走。循环控制直走,但是走完直线之后,记得要来一句判断,如果走过头了,就走回来轨道上。

5)其他的也一样,走过头了,就走回来轨道上,然后遇到了填着填着,遇到了已经走过的路(p[i][j]!=0),那么就应该拐弯了!

6)每次走到尽头时,以前进方向为基准,都要向右拐弯,然后向前跨一步,具体在坐标上的表现为++row,--row,++col,--col,这个很直观的,实在不理解的话,就自己画图就好了。

7)按4),5),6)的模拟贪吃蛇的爬动,一直到了把最后一个数n*n填完,就完成了蛇形填数这个任务了!

附上程序运行截图:


换一个起点的话,从右上角开始,设置int row=0, col=n, now=0, dir=1;效果如下:


但是,如果是比3大的数的话,由于数字的长度不一,就会出现整齐的界面:


(⊙o⊙)…这个嘛,自己手动添加一个格式化输出控制就好了,其实只需要在display函数里面改动就好了,这就是模块化的效果,除了提高重用率(在别的地方也可以用这个函数来达到相同的效果,直接copy过去就可以用),对于程序的维护还变得更简单了!比如以下的效果:微笑


好啦,我知道我的文字撰写能力很差,我会认真改的,大笑晚安。


0 0
原创粉丝点击