首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

矩陣區域旋轉:5×5 陣列局部 90 度翻轉完整解析

     編輯:關於C

問題描述

輸入 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)];
            }
        }
    }
}

關鍵實作細節

  1. 雙緩衝策略:讀入 a,操作寫入 b,未旋轉區域直接複製,避免覆蓋問題
  2. 邊界判斷:`i == r || i == r+1` 精確鎖定 2×2 區域;`i >= r && i <= r+2` 鎖定 3×3
  3. 相對座標轉換:`(i-r, j-c)` 為區域內相對位置,套用公式後換算回絕對座標
  4. 多測資處理:`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];
        }
    }
}

常見錯誤

  • 座標 1-based/0-based 混淆
  • 順/逆時針公式搞反
  • 原地旋轉導致資料覆蓋(需雙緩衝或暫存)
  • 邊界判斷寫錯(如 `<=` vs `<`)

這道題目考察矩陣座標變換與邊界控制,是陣列操作進階練習的優秀範例。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved