蛇形填数

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

//蛇形填数
#include 
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;
	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大的数的话,由于数字的长度不一,就会出现整齐的界面:

蛇形填数_第1张图片

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

蛇形填数_第2张图片

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


你可能感兴趣的:(模拟算法,蛇形填数)