輸入 5×5 矩陣,再輸入操作指令(類型、大小、左上角座標),對指定子矩陣進行 90 度順/逆時針旋轉,輸出旋轉後的完整矩陣。
| t1 t2 | 意義 | 影響範圍 |
|---|---|---|
| 1 2 | 順時針 90° | 2×2 區域(4 個元素) |
| 1 3 | 順時針 90° | 3×3 區域(9 個元素) |
| 2 2 | 逆時針 90° | 2×2 區域 |
| 2 3 | 逆時針 90° | 3×3 區域 |
座標 (x,y) 為 1-based,轉 0-based 後為左上角。
輸入: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 3 1 1 ← 順時針 90°,3×3,左上角 (1,1) → 0-based (0,0) 輸出: 11 6 1 4 5 12 7 2 9 10 13 8 3 14 15 16 17 18 19 20 21 22 23 24 25
左上 3×3 旋轉前:
1 2 3 6 7 8 11 12 13
順時針 90° 後:
11 6 1 12 7 2 13 8 3核心演算法:座標映射公式
對 N×N 子矩陣(N=2 或 3),左上角 (r, c);區域內相對座標 (i, j) 其中 0≤i,j<N。
順時針 90°:
新位置 (i, j) ← 舊位置 (N-1-j, i) b[r+i][c+j] = a[r + (N-1-j)][c + i]逆時針 90°:
新位置 (i, j) ← 舊位置 (j, N-1-i) b[r+i][c+j] = a[r + j][c + (N-1-i)]完整 C 語言實作
#include <stdio.h> #include <stdlib.h> void turn904(int (*a)[5], int (*b)[5], int row, int col, int type); void turn909(int (*a)[5], int (*b)[5], int row, int col, int type); int main() { int a[5][5], b[5][5]; int t1, t2, row, col; while (scanf("%d", &a[0][0]) != EOF) { // 讀取完整 5×5 矩陣 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (i == 0 && j == 0) continue; scanf("%d", &a[i][j]); } } scanf("%d %d %d %d", &t1, &t2, &row, &col); row--; col--; // 轉 0-based // 複製原矩陣到 b(未旋轉區域保持原樣) for (int i = 0; i < 5; i++) for (int j = 0; j < 5; j++) b[i][j] = a[i][j]; // 執行對應旋轉 if (t1 == 1 && t2 == 2) turn904(a, b, row, col, 0); else if (t1 == 1 && t2 == 3) turn909(a, b, row, col, 0); else if (t1 == 2 && t2 == 2) turn904(a, b, row, col, 1); else if (t1 == 2 && t2 == 3) turn909(a, b, row, col, 1); // 輸出結果 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { printf("%d%c", b[i][j], j == 4 ? '\n' : ' '); } } } return 0; } void turn904(int (*a)[5], int (*b)[5], int r, int c, int type) { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if ((i == r || i == r+1) && (j == c || j == c+1)) { if (type == 0) // 順時針 b[i][j] = a[r + 1 - (j-c)][c + (i-r)]; else // 逆時針 b[i][j] = a[r + (j-c)][c + 1 - (i-r)]; } } } } void turn909(int (*a)[5], int (*b)[5], int r, int c, int type) { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if ((i >= r && i <= r+2) && (j >= c && j <= c+2)) { if (type == 0) // 順時針 b[i][j] = a[r + 2 - (j-c)][c + (i-r)]; else // 逆時針 b[i][j] = a[r + (j-c)][c + 2 - (i-r)]; } } } }關鍵實作細節
- 雙緩衝策略:讀入 a,操作寫入 b,未旋轉區域直接複製,避免覆蓋問題
- 邊界判斷:`i == r || i == r+1` 精確鎖定 2×2 區域;`i >= r && i <= r+2` 鎖定 3×3
- 相對座標轉換:`(i-r, j-c)` 為區域內相對位置,套用公式後換算回絕對座標
- 多測資處理:`while(scanf(...) != EOF)` 支援多組輸入
通用化擴展
若需支援任意 N×N 區域旋轉:
void rotate_submatrix(int (*a)[5], int (*b)[5], int r, int c, int N, int clockwise) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (clockwise) b[r+i][c+j] = a[r + N-1-j][c + i]; else b[r+i][c+j] = a[r + j][c + N-1-i]; } } }常見錯誤
這道題目考察矩陣座標變換與邊界控制,是陣列操作進階練習的優秀範例。