题目
对于下面的4×4的矩阵,
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
对其进行Z字形扫描后得到长度为16的序列:
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
请实现一个Z字形扫描的程序,给定一个n×n的矩阵,输出对这个矩阵进行Z字形扫描的结果。
思路
一开始我是暴力破解,一个个方向来,写出来64行,思路也不清晰,后来在网上看到一个思路,就是把转过来思考一下,如下图:
然后就发现,这就像一个数塔,总共有2*n - 1层,而且按Z顺序扫描的元素的下标都具有对称性,如下图解释:
可以看到每层从左往右,下标x递减,y递增,从右往左则相反,然后奇数层就是从左往右,偶数层从右往左,所以利用这些对称性,我们可以写出精简的代码。
代码
#include <bits/stdc++.h>
int arr[510][510];
int n;
void zScan(int lever,bool isEven){
int x,y;//确定起点坐标
x = lever > n ? n : lever;
y = lever > n ? (lever - n + 1) : 1;
char c;//选择输出间隔符号
c = (x == n && y == n) ? '\n' : ' ';
int times;//限制每层递减/递增次数
times = lever >= n ? (n - (lever - n)) : lever;
if(isEven) std::swap(x,y);//偶数层时,交换x,y即可得到起点坐标
for(int i = 0; i < times; i++)//每层对起点坐标作用times次,然后输出对应元素即可
printf("%d%c",isEven ? arr[x++][y--] : arr[x--][y++],c);
return ;
}
int main(){
std::cin >> n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
std::cin >> arr[i][j];
for(int lever = 1; lever <= 2 * n - 1; lever++)//循环层数
zScan(lever,lever % 2 == 0);
return 0;
}