两种蛇形矩阵
在经历了无数个大坑,一步步调整,这玩意对初学者太不友好了,不过它可以提高你对于矩阵的理解,快速掌握二位数组!
今天主要说两种形式的矩阵:
第一种:绕圈型蛇形矩阵
样例如下:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
这种数组的写法比较奇特,在看了网上很多教程之后我感觉还是较为繁杂,因此我建议小白可以学习一下这种写法,很方便,记下来就好。代码如下,会附赠讲解
#include <iostream>
using namespace std;
int main() {
int a[100][100];
int x = 1, y = 0, k = 1;
int n;
cin >> n;
while (k <= n * n) {
;
while (y < n && !a[x][y + 1]) a[x][++y] = k++;
while (x < n && !a[x + 1][y]) a[++x][y] = k++;
while (y > 1 && !a[x][y - 1]) a[x][--y] = k++;
while (x > 1 && !a[x - 1][y]) a[--x][y] = k++;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
printf("%5d", a[i][j]);
}
printf("\n");
}
return 0;
}
这个的思路就是,一圈一圈的去思考,但我们并不是一圈一圈来写循环。
外面套个while保证次数和k的大小有关,不过请注意,这里的k是要小于等于。
内层的话,我来解释几个地方:
!a[x][y + 1]的意思就等同于a[x][y + 1] == 0 用来判断下一位是不是为空
注意也要分清楚++y和y++之间的区别,我们是站在一个点去看待下一个点的数值
a[x][++y] is equal to y++; a[x][y] = k; k++;
那么有人会问了,你这是逆时针的方向,我偏要写顺时针的方向那咋整;
你只需要改一下初始条件: x = 0, y = 1;循环体里面把第二个和第一个调换第四个和第三个调换就可以了,这样就ok了;
最后提醒一句,这个写法容易死循环(主要是我手欠写错条件,嘿嘿警示你们了哈, 写代码一定要走心啊
question 2
接下来我们便请出第二位重量级选手:拐弯蛇形矩阵(貌似第一个也拐弯。。orz
输出样例
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16
这个数组着实花费了我不少时间,目前我也没想出来更好的解决方法,主要是找不到数学规律
代码如下,稍后讲解:
#include <iostream>
using namespace std;
int main() {
int n, m, i, j, k = 1, h;
cin >> n;
int a[120][100];
for (i = 1; i <= n; i++) {
j = i + 1;
if (i % 2) { //jishu
for (h = 1; h <= i; h++) {
a[j - h][h] = k++;
}
} else {
for (h = 1; h <= i; h++) {
a[h][j - h] = k++;
}
}
}
for (; i <= n * 2 - 1; i++) {
j = i + 1;
if (i % 2) { //jishu:
for (h = n; h >= i - n + 1; h--) {
a[h][j - h] = k++;
}
} else {
for (h = n; h >= i - n + 1; h--) {
a[j - h][h] = k++;
}
}
}
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
printf("%5d", a[i][j]);
}
printf("\n");
}
return 0;
}
这个问题最重要的就是找到每一斜行的循环起点表示方法,以及循环次数!!!!!!
开始漫长的讲解:
这个题目我的思路是这样的,斜着去看待每一排,也就是说这样的一排下标数之和是相等的,我们只需要找到起始条件就可以了。
首先我们知道一共有 2 * n - 1个斜行,首先我们要去判断第一行到第n行 ,为什么我们要先判断1到n呢 ? 因为他们的起始位置在 (1 , x ) 或者是 (x,1)这样的位置,而到了 n + 1 以后的位置起始点就是(n, x)或者是 (x, n)。
我们先分析1到n(其实第n行也可以放到后面进行处理,反正为了方便我写了两个大循环)
从1到n每一斜行下标之和为 j = i + 1;判断i是奇数还是偶数,如果是奇数就先从左下角开始循环,如果是偶数,就在右上角开始循环。每一个循环循环的次数就等于i值。
这样就写出来了
j = i + 1;
if (i % 2) { //jishu
for (h = 1; h <= i; h++) {
a[j - h][h] = k++;
}
} else {
for (h = 1; h <= i; h++) {
a[h][j - h] = k++;
}
}
对于 n + 1 到2 * n - 1的循环我费了不少时间,没有找到正确思路吧,主要是考虑起始点和循环次数的问题
这一部分循环不等同于前面的循环,是从n开始减少
if (i % 2) { //jishu:
for (h = n; h >= i - n + 1; h--) {
a[h][j - h] = k++;
}
} else {
for (h = n; h >= i - n + 1; h--) {
a[j - h][h] = k++;
}
}
还是老样子,如果掉头的方向发生了变化就把奇数部分和偶数部分换过来就OK了
最后,祝福每一个写代码的朋友吧,生活不易,看完了点个赞再走吧, 要是能加个关注就更好了,嘻嘻,谢了,时间不早了,快两点了,早休息啊!