问题描述
  在图像编码的算法中,需要将一个给定的方形矩阵进行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的正整数。
题目的分析解答:
     这里提供两种解题思路,一种是纯找规律来进行实现的,还有一种是基于Z字形扫描的较常规处理办法,下面我们来详细介绍一下这两种解法。
其一:对矩阵的元素进行分析,发现扫描的路径大致是这样的:
0:  a[0][0]
1:  a[0][1]->a[1][0]
2:  a[2][0]->a[1][1]->a[0][2]
3:  a[0][3]->a[1][2]->a[2][1]->a[3][0]
4:  a[3][1]->a[2][2]->a[1][3]
5:  a[2][3]->a[3][2]
6:  a[3][3]
显然发现整个扫描过程是从0扫到2*(n-1)的,而且矩阵的两个下标之和等于扫描的顺序i,所以每一次只需要判断矩阵的扫描是从某一行开始还是从某一列开始,经过观察发现当扫面过程处于偶数时是在列开始的,因此整个过程就很好确定了。源代码如下所示:

#include<iostream>
#include<vector>
using namespace std;

int main()
{ int n;
cin>>n;
int a[500][500]={0};
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>a[i][j];
}
}
for(int i=0;i<=(2*(n-1));i++)
{
for(int k=0;k<n;k++ )
{
for(int j=0;j<n;j++)
{
if(k+j==i)
{
if(i%2==0)
{
cout<<a[j][k]<<" ";
}else{

cout<<a[k][j]<<" ";
}
}
}
}
}

return 0;
}

其二:

分析这类题,首先要找出扫描的规律,从题目中可以发现,扫描是成Z字形的。那么也就是说对于扫描输出有四种状态,每次输出要判定下一次的行走路线,走一步就输出一个。

四种状态为{right,leftDown,down,rightUp}。

开始我还怀疑,Z字形扫描矩阵是否能够遍历矩阵所有的元素。下面我们来分析一下:

1、前提是这个矩阵是一个n维方阵,假设为Anxn.

2、从输出当前的元素A[i][j],并根据当前的状态来判断下一步的扫描状态。该如何判断呢?可以发现每次在执行完当前状态后,行号i或者列号j都有可能发生改变,那么就可以结合当前状态和行,列号的取值来判定下一步的行走路线。

从上图中我们可以发现:

right状态始终在首行或者尾行上执行,并且执行right状态后列号j会增加1,即j = j+1。所以我们可以根据当前状态的下一步状态有两种:

当i == 0时,state = leftDown;

当i == n-1时,state = rightUp。

执行完leftDown状态后,i = i+1,j = j-1,其下一步状态有三种:

当 j == 0 && i != n-1时,state = down;

当 row == n-1时,state = right;

其它情况,state = leftDown(自身状态)。

对于rightUp和down状态,其分析方法和上面两种类似,就不再做分析。

综合上面分析来看,状态每次要发生改变的话,行号或者列号必须处于临界状态,即它们的取值为{0,n-1}。

#include <iostream>

using namespace std;

int A[501][501];
enum Choice
{
rightTowards,//向移动
rightUp,//向右上移动
down,//向下移动
leftDown//向左下移动
}; void zigzagScan(int n)
{
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cin >> A[i][j];
int row = 0, col = 0;
Choice choice = rightTowards;
//row = n-1&&col = n-1的情况在while循环结束后处理,防止出现越界的情况
while (row != n - 1 || col != n - 1)
{
cout << A[row][col] << ' ';
switch (choice)
{
case rightTowards:
col++;
if (row == 0)
choice = leftDown;
else
choice = rightUp;
break;
case rightUp:
row--;
col++;
if (row == 0 && col != n - 1)
choice = rightTowards;
else if (col == n - 1)
choice = down;
else
choice = rightUp;
break;
case down:
row++;
if (col == 0)
choice = rightUp;
else
choice = leftDown;
break;
case leftDown:
row++;
col--;
if (col == 0 && row != n - 1)
choice = down;
else if (row == n - 1)
choice = rightTowards;
else
choice = leftDown;
break;
}
}
cout << A[n - 1][n - 1];
} void main(void)
{
int n;
while (cin >> n)
{
zigzagScan(n);
}
}
 

Z字形扫描(201412-2)的更多相关文章

  1. CCF——Z字形扫描问题

    试题编号: 201412-2 试题名称: Z字形扫描 时间限制: 2.0s 内存限制: 256.0MB 问题描述: 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag ...

  2. [CCF] Z字形扫描

    CCF Z字形扫描 感觉和LeetCode中的ZigZag还是有一些不一样的. 题目描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z ...

  3. CCF真题之Z字形扫描

    201412-2 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的4×4的矩阵, 1 5 ...

  4. CCF系列之Z字形扫描(201412-2)

    试题编号:201412-2试题名称:Z字形扫描时间限制: 2.0s内存限制: 256.0MB 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n ...

  5. CCF CSP 201412-2 Z字形扫描

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201412-2 Z字形扫描 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫 ...

  6. Z字形扫描矩阵

    问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的4×4的矩阵, 1 5 3 9 3 7 5 ...

  7. CSP201412-2:Z字形扫描

    引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...

  8. 201412-2 Z字形扫描(c语言)

    问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的4×4的矩阵, 1 5 3 9 3 7 5 ...

  9. CCF201412-2 Z字形扫描 java(100分)

    试题编号: 201412-2 试题名称: Z字形扫描 时间限制: 2.0s 内存限制: 256.0MB 问题描述: 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag ...

随机推荐

  1. java 中抽象类和接口的五点区别?

    1.一个类可以实现多个接口 ,但却只能继承最多一个抽象类. 2.抽象类可以包含具体的方法 , 接口的所有方法都是抽象的. 3.抽象类可以声明和使用字段 ,接口则不能,但接口可以创建静态的final常量 ...

  2. 每日Scrum站会实践推荐

    流程 1.团队在Scrum 白板前集中,推荐围成一个半圆形状. 2.最左边的成员开始讲述昨天/上一次Scrum每日站会后到现在为止,完成了什么任务,只需讲对应的任务就行了,不要讲很长的故事. 3.讲述 ...

  3. ZooKeeper:Java客户端网络处理

    了解ZooKeeper客户端的实现,对于使用ZooKeeper的客户端非常重要. 通过对客户端源码的阅读,了解了如下信息: 创建ZooKeeper对象时,应会创建一个ClientCnxn(代表了客户端 ...

  4. sql语句with as 和with(nolock)

    当with和as一起用时,表示定义一个SQL字句 例: with sonword as ( select * from person  ) select * from  student where n ...

  5. android 获取IMSI信息(判断是移动,联通,电信手机卡)

    首先我们需要知道手机IMSI号前面3位460是国家,紧接着后面2位00 02是中国移动,01是中国联通,03是中国电信.那么第一步就是先获取手机IMSI号码:代码如下 /** *获取IMSI信息 * ...

  6. 排序算法----基数排序(RadixSort(L,max))单链表版本

    转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割 ...

  7. JS中字符串的true转化为boolean类型的true

    var a="True"; a = eval(a.toLowerCase()); alert(typeof a); //boolean alert(a);//true 正解,eva ...

  8. spring3系列一

    IOC基础 Ioc是什么 Ioc--Inversion of Control 控制反转,不是什么技术,而是一种设计思想.在java开发中,ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对 ...

  9. 基于ionic+angulajs的混合开发实现地铁APP

    基于ionic+angulajs的混合开发实现地铁APP 注:本博文为博主原创,转载时请注明出处. 项目源码地址:https://github.com/zhangxy1035/SubwayMap 一. ...

  10. sed awk grep三剑客常用

    sed的常用用法: awk的常用用法: grep的常用用法: 除了列出符合行之外,并且列出后10行. grep -A 10 Exception kzfinance-front.log 除了列出符合行之 ...