题解好少
在图像编码的算法中,需要将一个给定的方形矩阵进行 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 字形扫描后的结果。
数据范围
$1小于n小于500$,
$矩阵元素为不超过 1000 的正整数$。
输入样例:
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
找规律
这个的话可以拆分成两部分来做。
然后的话我比较菜,觉得比较麻烦,于是写了两个move函数表示移动一条对角线。
当然大佬们可以合二为一,这里就不说了。
规律跟大家说一下把,就是x++y--
或者y++x--
,然后只要碰到边缘就改变x和y。
然后记录一个cnt,注意要看看到边界的时候是往右走还是往下走,然后每次都要调换一下x和y。
反正就是个毒瘤模拟,调一调按说半小时之内搞定。
c++代码:
应该比较简短了8
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
int n;
int a[N][N];
int now;
int cnt = 0;
void move(int sx, int sy)
{
if(sx > sy) swap(sx, sy);
int x = sx, y = sy;
while(true)
{
cout << a[x][y] << ' ';
if(x == sy && y == sx) break;
x ++, y --;
}
}
void move2(int sx, int sy)
{
if(sx < sy) swap(sx, sy);
int x = sx, y = sy;
while(true)
{
cout << a[x][y] << ' ';
if(x == sy && y == sx) break;
x --, y ++;
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
cin >> a[i][j];
int px = 1, py = 1;
while(true)
{
if(cnt % 2 == 0) move2(px, py);
else move(py, px);
swap(px, py);
if((px == 1 && py == n) || (px == n && py == 1))
{
break;
}
if(px == 1 || py == 1 || px == n || py == n)
{
if(cnt % 2 == 0) px ++;
else py ++;
cnt ++;
}
}
if(n % 2 == 0) px = n, py = 2, cnt = 0;
else px = 2, py = n, cnt = 1;
while(true)
{
if(cnt % 2 == 0) move2(px, py);
else move(py, px);
swap(px, py);
if(px == n && py == n)
{
break;
}
if(px == 1 || py == 1 || px == n || py == n)
{
if(cnt % 2 == 0) px ++;
else py ++;
cnt ++;
}
}
}
时间复杂度应该是n方的,因为每个点都只走了一遍