1050.螺旋矩陣-PAT乙級
阿新 • • 發佈:2020-08-18
本題要求將給定的 N 個正整數按非遞增的順序,填入“螺旋矩陣”。所謂“螺旋矩陣”,是指從左上角第 1 個格子開始,按順時針螺旋方向填充。要求矩陣的規模為 m 行 n 列,滿足條件:m×n 等於 N;m≥n;且 m−n 取所有可能值中的最小值。
輸入格式:
輸入在第 1 行中給出一個正整數 N,第 2 行給出 N 個待填充的正整數。所有數字不超過 104,相鄰數字以空格分隔。
輸出格式:
輸出螺旋矩陣。每行 n 個數字,共 m 行。相鄰數字以 1 個空格分隔,行末不得有多餘空格。
輸入樣例:
12 37 76 20 98 76 42 53 95 60 81 58 93
輸出樣例:
98 95 93 42 37 81 53 20 76 58 60 76
分析:N=m x n其中m>=sqrt(N)>=n,所以讓m、n=sqrt(N),若此時m x n<N則m++,m x n>N則n--,若m x n=N則找到滿足條件的m、n。申請m x n陣列,將排序號的陣列元素按以下方式填入(狀態機思想):定義四種狀態(UP\DOWN\LEFT\RIGHT)檢測條件轉變狀態。題目中的矩陣是順時針填充,即遍歷方向是 起點 -> 向右填充 -> 向下填充 -> 向左填充 -> 向上填充 -> 向右填充...迴圈往復,全部填滿時結束。當我們完成每一個橫向或豎向填充過後,要填充的矩陣縮小,因此我們修改矩陣的四點座標(右上角為座標起點(0,0))四點座標分別為(min_i, min_j)、(min_i, max_j)、(max_i, max_j)、(max_i, min_j)然後進行下一方向填充。即可得到結果。
#include <iostream> #include <vector> #include <math.h> #include <algorithm> #define LEFT 0 #define RIGHT 1 #define UP 2 #define DOWN 3 using namespace std; int main() { int N, m, n; cin >> N; vector<int> v(N); for (int i = 0; i < N; i++) cin >> v[i]; m = n = sqrt(N); while (m * n != N) { if (m * n > N) n--; else m++; } sort(v.begin(), v.end()); vector<vector<int>> res(m, vector<int>(n)); int state = RIGHT; int max_i = m - 1, max_j = n - 1, min_i = 0, min_j = 0, i = 0, j = 0; for (int k = N - 1; k >= 0; k--) { int temp = v[k]; switch (state) { case LEFT: if (j == min_j) { state = UP; max_i--; res[i--][j] = temp; } else res[i][j--] = temp; break; case RIGHT: if (j == max_j) { state = DOWN; min_i++; res[i++][j] = temp; } else res[i][j++] = temp; break; case UP: if (i == min_i) { state = RIGHT; min_j++; res[i][j++] = temp; } else res[i--][j] = temp; break; case DOWN: if (i == max_i) { state = LEFT; max_j--; res[i][j--] = temp; } else res[i++][j] = temp; break; } } for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) cout << res[i][j] << ((j == n - 1) ? "\n" : " "); return 0; }