Z字形掃描矩陣


問題描述
  在圖像編碼的算法中,需要將一個給定的方形矩陣進行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字形的。那么也就是說對於掃描輸出有四種狀態,每次輸出要判定下一次的行走路線,走一步就輸出一個。

四種狀態為{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); } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM