# a417 - 螺旋矩陣 ### 題目連結: [a417](https://zerojudge.tw/ShowProblem?problemid=a417) ### 題目解析 * 依照題目的描述,需要輸出一個連續數字的二維矩陣 * 此矩陣的數字,會隨著矩陣的大小由左上角開始不斷標號,直到中心點 ### 題目類型 二維串列/矩陣/邊界問題 ### 範例測資解讀 * 輸入 * 第一行只有一個數字T,代表有幾組測試資料 * 接下來有T行,每行有兩個整數N, M * N代表矩陣長寬(正方形) * M代表旋轉的方向(1=順時鐘, 2=逆時鐘) * 輸出 * 輸出為一個二維矩陣,並且需要有足夠的間隔 * 輸出說名的 setw(5) 為C/C++的語法,不適用於 Python ### 其他注意事項 * 進行二維串列計算的時候需要小心並且考慮邊界問題,避免發生 list out of range 的錯誤 ### 程式解析 由題目中可以瞭解,我們需要將數字依照順時鐘或逆時鐘的方式,不斷旋轉填入矩陣中,矩陣是數學上的一種特殊結構,但在這個題目其實就是使用二維串列儲存資料的意思 順時鐘的填法: ![](https://i.imgur.com/3krOIEU.png, =300x) 逆時鐘的填法: ![](https://i.imgur.com/q0QUK0j.png, =300x) 要如何使用程式在二維串列中移動呢? 首先需要知道二維串列中,相連元素之間索引值的關係 移動時需要兩個索引值,定義為 r_index(上下移動), c_index(左右移動) 另外還需要旋轉方向: * 如果是順時針,則移動方向依序為右下左上 * 如果是逆時針,則移動方向為下右上左 ``` python r_index = 0 c_index = 0 direction = 1 # 1: right # 2: down # 3: left # 4: up ``` 如果左上角1的位置為起始點,往下移動的話,需要調整 r_index 的位置 如果要往右移動的話,需要調整 c_index 的位置,以這兩個索引值就能達到在二維串列中移動的方法 ![](https://i.imgur.com/zxEi9lG.png, =250x) ### 轉向和邊界 當移動 r_index, c_index 的時候碰到陣列的邊界就需要進行轉向,否則會發生錯誤或是數字填錯 ![](https://i.imgur.com/VR3NSxx.png, =300x) 哪邊是陣列的邊界呢?在設計判斷條件的時候必須特別注意這個範圍 * r_index<0, r_index>=N * c_index<0, c_index>=N ※ 除了碰到邊界需要轉向以外,也需要考慮是會碰到已填入值的位置 ![](https://i.imgur.com/ajlzohQ.png, =300x) ### 完整程式碼 (僅提供參考) ``` python=01 arr = [] for x in range(100): arr.append([ -1 for i in range(100) ]) def show(n): for i in range(n): for j in range(n): #print(arr[i][j], end=' ') print("%5d" % arr[i][j], end='') print() while True: try: #start N = int(input()) M = int(input()) for i in range(N): for j in range(N): arr[i][j] = 0 if M==1: r_index = 0 c_index = 0 num = 1 direction = 1 # 1: right # 2: down # 3: left # 4: up while num<=N*N : # 向右移動 if direction == 1: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 c_index +=1 #判斷邊界和轉向,修改 r_index, c_index 的計算方法 if c_index>=N or arr[r_index][c_index]>0: c_index -=1 r_index +=1 direction = 2 else: direction = 2 #end of if direction ==1 elif direction == 2: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 r_index +=1 if r_index>=N or arr[r_index][c_index]>0: r_index -=1 c_index -=1 direction = 3 else: direction = 3 #end of if direction ==2 elif direction == 3: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 c_index -=1 if c_index<0 or arr[r_index][c_index]>0: c_index +=1 r_index -=1 direction = 4 else: direction = 4 #end of if direction ==3 elif direction == 4: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 r_index -=1 if c_index<0 or arr[r_index][c_index]>0: r_index +=1 c_index +=1 direction = 1 else: direction = 1 #end of if direction ==3 #end of if M==1 else: r_index = 0 c_index = 0 num =1 direction = 1 while num<=N*N: if direction == 1: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 r_index +=1 if r_index >=N or arr[r_index][c_index]>0: r_index -=1 c_index +=1 direction = 2 else: direction = 2 #end of if direction == 1 elif direction == 2: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 c_index +=1 if c_index >=N or arr[r_index][c_index]>0: c_index -=1 r_index -=1 direction = 3 else: direction = 3 #end of if direction == 2 elif direction == 3: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 r_index -=1 if r_index <0 or arr[r_index][c_index]>0: r_index +=1 c_index -=1 direction = 4 else: direction = 4 #end of if direction == 3 elif direction == 4: if arr[r_index][c_index] == 0: arr[r_index][c_index] = num num +=1 c_index -=1 if c_index <0 or arr[r_index][c_index]>0: c_index +=1 r_index +=1 direction = 1 else: direction = 1 #end of if direction == 4 show(N) except: break ``` ###### tags: `基礎15題解` `APCS` `ZeroJudge`