题目
问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan)。给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的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字形扫描的结果。 输入格式 输入的第一行包含一个整数n,表示矩阵的大小。 输入的第二行到第n+1行每行包含n个正整数,由空格分隔,表示给定的矩阵。 输出格式 输出一行,包含n×n个整数,由空格分隔,表示输入的矩阵经过Z字形扫描后的结果。 样例输入 4 1 5 3 9 3 7 5 6 9 4 6 4 7 3 1 3 样例输出 1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3 评测用例规模与约定 1≤n≤500,矩阵元素为不超过1000的正整数。
(就不贴图了)
思路
1.主要就是判断到了边界上的时候怎么走,比如如果现在位置为(i,j),可以继续往下走(i!=n-1),那么位置变成(i+1,j);如果不可以往下走,也就是走到了下边界上了,那么只能向右走,那么位置变成(i,j+1)。处理右边界同理。
2.判断完边界后,主要就是中间值要怎么控制输出的问题了。本来发现了斜线相连的几个相邻点上的i+j之和是一样的,然后觉得也许需要用到这个条件来控制输出。想了一下,这样对于同一条斜边上的输出顺序会不会有点难控制,毕竟有的是斜向上,有的是斜向下。但其实也应该是可行的,只不过有点拗。
3.现在选用的是看了一个博主的解法,给我的启示。因为这个Z字形走的顺序是固定的,其实是分为四个阶段就是一个轮回(从上边界上的点(0,j)回到上边界的点(0,j+2))。首先是向右,然后斜向左下方,再向下,最后斜向右上方。所以写一个循环,分别把这四个过程都描述清楚,然后依次输出即可。
4.这个题目过程碰到的问题主要就是:本来是想把沿着边界变换后的位置输出,放在两个循环外面,就是完完整整的四个阶段,每个阶段有各自的输出。但是这样的话如果n=1,就会多出两个在外面的输出(第一二阶段,因为一二阶段本来是设置不需要判断的直接输出);其次就是捋顺i和j的变换,多加了就要多减;最后就是判断结束的条件,我很不习惯这样的写法,所以每次需要同时判断i和j 的时候总是写成双重for循环,实现不了目标。
题解
#include<iostream> using namespace std; #define MAX 501 int matrix[MAX][MAX]; int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ scanf("%d",&matrix[i][j]); } } int i=0; int j=0; printf("%d ",matrix[i][j]); while(i<n && j<n && i+j!=2*(n-1)){ if(j==n-1){ i++; } else{ j++; } while(j>=0 && i<=n-1){ if(i==n-1 && j==n-1){ printf("%d\n",matrix[i][j]); break; } else{ printf("%d ",matrix[i][j]); } i++; j--; } i--; j++; if(i==n-1){ j++; } else{ i++; } while(j<=n-1 && i>=0){ if(i==n-1 && j==n-1){ printf("%d\n",matrix[i][j]); break; } else{ printf("%d ",matrix[i][j]); } i--; j++; } i++; j--; } return 0; }