题目
标题
Z字形扫描
类别
数组
时间限制
1S
内存限制
256Kb
问题描述
在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan)。给定一个m×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。分成两个部分。*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,a[100][100],i=0,j=0; //x代表行数,y代表列数而不是横纵坐标,i,j是计数器
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&a[i][j]);
}
}
printf("%d ",a[0][0]);
int x=0,y=1;
for(i=1;i<n;i++) /*此时i代表长度递增的行序数,从0开始,使其与扫描时移动的次数
(也就是行的长度)相等,从第0行到第n-1行,共n行*/
{
if(i&1) //将每一斜行看作一行。若i&1==1,则i为奇数。奇数行的扫描方向为左下。
{
for(j=0;j<i;j++) //扫描第i行时向左下移动的次数为i
{
printf("%d ",a[x++][y--]); /*x++和y--即可实现向左下扫描。注意自增特
点。该处相当于a[x][y],x++,y++。用后自增的
原因是,让扫描到奇数行时,xy值已经对应了
该行的第一个。如果用前自增,当扫描到奇数行时,
xy值仍对应的是上一行的末尾。*/
}
printf("%d ",a[x++][y]); //到边界后向下移动
}
else //若i&1==0,则i为偶数。偶数行的扫描方向为右上。
{
for(j=0;j<i;j++) //扫描第i行时向右上移动的次数为i
{
printf("%d ",a[x--][y++]); //x--和y++即可实现向右上扫描
}
printf("%d ",a[x][y++]); //到边界后向右移动
}
}
//这时已经扫描完了所有长度递增的行,最近一次扫描要么是左下角,要么是右上角
if(n&1) /*若n为奇数,则最近一次扫描是右上角,注意,最近一次扫描的是第n-1斜行,
扫描后,还有一个y++,也就是说,这时(y,x)的位置是右上角的右方*/
{
y--;/*回到右上角*/x++;//向下移动
}
else /*若n为偶数,则最近一次扫描是左下角,注意,最近一次扫描的是第n-1斜行,
扫描后,还有一个x++,也就是说,这时(y,x)的位置是左下角的下方*/
{
x--;/*回到左下角*/y++;//向右移动
}
for(i=n-2;i>=0;i--) /*此时i代表长度递减的行序数,从n-2开始,使其与扫描时移动的次数
(也就是行的长度)相等,从第n-2行到第0行,共n-1行*/
{
if(i&1)
{
for(j=0;j<i;j++)
{
printf("%d ",a[x++][y--]);
}
printf("%d ",a[x][y++]); //此时到边界后向右移动
}
else
{
for(j=0;j<i;j++)
{
printf("%d ",a[x--][y++]);
}
printf("%d ",a[x++][y]); //此时到边界后向下移动
}
}
return 0;
}
输出说明
在一行上输出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