題目網址 (多筆測資版 (https://zerojudge.tw/ShowProblem?problemid=b965))
矩陣是將一群元素整齊的排列成一個矩形,在矩陣中的橫排稱為列 (row) ,直排稱為行 (column) ,其中以 Xij 來表示 矩陣 X 中的第 i 列第 j 行的元素。 我們可以對矩陣定義兩種操作如下:
翻轉:即第一列與最後一列交換、第二列與倒數第二列交換、… 依此類推。
旋轉:將矩陣以順時針方向轉 90 度。
一個 矩陣 A 可以經過一連串的旋轉與翻轉操作後,轉換成 新矩陣 B 。 給定 矩陣 B 和一連串的操作,請算出原始的 矩陣 A 。
解題思路: 這題題目測資範圍 R,C,M 都小於 10,如果直接做的話複雜度應該就是 O (RCM)(就是按照題目的意思把輸入的矩陣反著操作),限制 2s 應該是可以順利通關
🌟因為是要從 B 推回原先的矩陣,因此需要將輸入指令倒著走一次(例如原本是 A 矩陣翻轉、翻轉、順時針旋轉 90 度得到 B 矩陣,就要將 B 矩陣逆時針旋轉 90 度、翻轉、翻轉,才能變成原先的 A 矩陣),因此現在問題就只剩下如何完成翻轉和逆時針旋轉 90 度了
- 翻轉:這邊是指上下翻轉,因此較為簡單,只要將第 i 列第 j 行的元素跟第 (c-i) 列第 j 行的元素交換即可,且其中 i 跟 (c-i) 會在一半的地方交會,且在 c 是奇數時 (c+1)/2 的那行可以不做任何操作,因此讓 i 從 0~c/2 執行過一次即可
- 逆時針旋轉 90 度:這個稍微難一點,可以想做事將左上角固定,逆時針旋轉 90 度,如此一來可以發現就是將 (i,j) 位置的元素移動到 (r-j-1,i)
✏️多筆測資就只要把一開始的輸入包在 while 裡就好了
b965. 第 2 題 矩陣轉換 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <bits/stdc++.h> using namespace std;
int arr[11][11]; int c,r,m;
void turn(){ int tmp[11][11]; for(int i = 0; i<c; i++) for(int j = r-1; j>=0; j--) tmp[r-1-j][i]=arr[i][j]; swap(c,r); for(int i = 0; i< c; i++) for(int j = 0; j<r; j++) arr[i][j] = tmp[i][j]; }
void reverse(){ for(int i = 0; i<c/2; i++) for(int j = 0; j<r; j++) swap(arr[i][j], arr[c-1-i][j]); }
signed main(){ ios::sync_with_stdio(0); cin.tie(0); while(cin >> c >> r >> m){ for(int i = 0; i< c; i++) for(int j = 0; j<r; j++) cin >> arr[i][j]; bool cmd[11]; for(int i = 0; i<m; i++) cin >> cmd[i]; for(int i = m-1; i>=0; i--){ if(cmd[i]) reverse(); else turn(); } cout << c << ' ' << r << '\n'; for(int i = 0; i< c; i++){ for(int j = 0; j<r; j++){ cout << arr[i][j]; if(j<r-1) cout << ' '; } cout << '\n'; } } return 0; }
|