算法初步——番外(1):回形矩阵/蛇形矩阵
前言
今天在刷题的时候,突然碰到了一年前在学校C语言上机课时偶遇的一道题——回形(又称蛇形)矩阵问题
大概就是要输出这么一个矩阵:
当时在遇到这个问题时我就很犯难,犹记得当时好像是从逻辑上遍历然后if()一个个检索. . .最后好像还没跑出来
所以今天想要再好好思考一下这道题到底采用什么样的办法可以简化我们的代码量和逻辑判断的思考量。
一、问题阐述
二、思路简述:
上面这张图是我们的一般分析方法
而这张图则说明了方向变化可以通过dx,dy矩阵实现
是不是有些不理解dx,dy?
没关系
在详细解释dx,dy之前我们来看一下”填数方向“
我们先往右边填数,这个时候每填一个坐标变化是不是(+0,+1)
接着我们的填数方向从向右变为了向下,每次坐标变化变为(+1,+0)
然后是向左,坐标变化是(+0,-1)
. . . . . .
再来看看我们的dx ={-1,0,1,0},dy={0,1,0,-1},
dx的第二项和dy的第二项是不是可以拼成{0,1},第三项可以拼成{1,0},第四项可以拼成{0,-1}. . . . . .
诶,发现了吗?选取dx和dy的指定项就可以实现一一对应!
每次变一个方向,就是往dx,dy中的项往后推一个单位。
那怎么推?
我们可以假定一个d = 1,然后每次(d+1)mod 4就可以了
是不是理解我的意思了?我们来实现一下吧!
三、上代码
代码如下:
#include <iostream>
using namespace std;
//先初始化数组和想要输入的行数和列数
int q[105][105],n,m;
int main(){
cin>>n>>m;
//定义我们的方向dx,dy,以及方向标”d“
int dx[] = {-1,0,1,0},dy[] = {0,1,0,-1};
int x=0,y=0,d=1;
for(int i=1;i<=n*m;i++){
q[x][y] = i;
//每次a,b指下一个填数坐标
int a =x+dx[d],b =y+dy[d];
//考虑如果超出数组边界或者前方即将填的空格已经被填充了,则立即转变方向,改写a,b
if(a<0 || a>=n || b<0 || b>=m || q[a][b])
{
d = (d+1)%4;
a = x+dx[d],b = y+dy[d];
}
x = a,y =b;
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cout<<q[i][j]<<" ";
cout<<endl;
}
return 0;
}
我们来看看最后的效果~