CCF 201412-2 Z字形掃描 JAVA實現
阿新 • • 發佈:2019-01-08
問題描述
在影象編碼的演算法中,需要將一個給定的方形矩陣進行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遞增到2*(n-1),n為矩陣行數,比如樣例輸入中1元素的座標為[0,0],行、列座標和為0,“斜線”上元素5和3座標分別為[0,1]和[1,0],行列座標和為1,元素3、7、9行列座標和為2.。。。。。。以此類推。所以我們將行列座標和相同的元素存到同一列裡面,如下所示,按照輸入順序將元素存到每一列中,i+j表示行列座標和,作為每一列的索引:
只要我們根據題意交替按反序和正序遍歷每一列,所遍歷的結果即為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字形掃描的結果。具體程式碼如下:
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class _12_02_other { public static void main(String[] args) { Scanner scanner=new Scanner(System.in); boolean mark=true;//用來標記交替正反遍歷每一列 int n=scanner.nextInt(); T[]S=new T[2*n-1];//n*n矩陣行列座標和從0到2*(n-1),故定義的列數為2*n-1 for(int i=0;i<=2*n-2;i++){ S[i]=new T(); } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ //行列和相同的存放同一列中 S[i+j].add(scanner.nextInt()); } } /* * 遍歷每一列 */ for(int i=0;i<S.length;i++){ if(mark){ S[i].outReverse(); mark=!mark; }else { S[i].outForward(); mark=!mark; } } scanner.close(); } } class T{ private List<Integer> L;//用來儲存每一列元素 public T(){ L=new ArrayList<>(); } public void add(int a){ L.add(a); } public void outForward(){//正序遍歷 for(int b:L){ System.out.print(b+" "); } } public void outReverse(){//反序遍歷 for(int i=L.size()-1;i>=0;i--){ System.out.print(L.get(i)+" "); } } }