문제에 주어진 조건들을 그대로 코드로 구현하는 전형적인 '시뮬레이션' 유형입니다.
문제를 편하게 설명하기 위해 배열을 형태의 배열 a
라 가정하겠습니다.
연산은 (1, 2) → (3, 4) → (5, 6) 순으로 구현이 어렵습니다.
최대한 RangeException
에 신경쓰면서 인덱스를 조작해보며 구현합니다.
배열을 상하 반전하기 위해서는 i
번째 행과 N-1-i
번째 행을 서로 교환해주면 됩니다.
주의할 점은 번째 행까지만 반전해주면 된다는 점입니다.
서로 대칭된 위치에 있는 두 행을 교환하는 방법은 두 가지가 있습니다.
각 요소끼리 교환합니다.
for (int y = 0; y < N; ++y) {
for (int x = 0; x < M; ++x) {
tmp = a[y][x];
a[y][x] = a[N - 1 - y][x];
a[N - 1 - y][x] = tmp;
// swap(a[y][x], a[N - 1 - y][x]);
}
}
2. 각 행끼리 교환합니다.
```cpp
for (int y = 0; y < N; ++y) {
for (int x = 0; x < M; ++x) tmp[x] = a[y][x];
for (int x = 0; x < M; ++x) a[y][x] = a[N - 1 - y][x];
for (int x = 0; x < M; ++x) a[N - 1 - y][x] = tmp[x];
}
```
배열을 좌우 반전하기 위해서는i
번째 열과 M-1-i
번째 열을 서로 교환해주면 됩니다.
역시 번째 열까지만 반전해줘야 문제가 발생하지 않습니다.
반전하는 방식은 1번 연산과 동일합니다.
for (int y = 0; y < N; ++y) {
for (int x = 0; x < M / 2; ++x) {
tmp[x] = a[y][x];
a[y][x] = a[y][M - 1 - x];
a[y][M - 1 - x] = tmp[x];
// swap(a[y][x], a[y][M - 1 - x]);
}
}
(0, 0), (0, 1), (0, 2), (0, 3)
은 (3, 0), (2, 0), (1, 0), (0, 0)
으로 옮겨집니다.(1, 0), (1, 1), (1, 2), (1, 3)
은 (3, 1), (2, 1), (1, 1), (0, 1)
로 옮겨집니다.(y, x)
는 (M - 1 - x, y)
로 옮겨집니다.(y, x)
는 (x, N - 1 - y)
로 옮겨집니다.N
과 M
이 바뀌어야 한다는 점입니다.N
과 M
이 바뀌지 않습니다.#include <iostream>
#include <vector>
using namespace std;
int N, M, R, op[1000];
vector<vector<int>> arr;
// 연산 1
void flipHorizontal() {
for (int y = 0; y < N / 2; ++y)
for (int x = 0; x < M; ++x)
swap(arr[y][x], arr[N - 1 - y][x]);
}
// 연산 2
void flipvertical() {
for (int y = 0; y < N; ++y)
for (int x = 0; x < M / 2; ++x)
swap(arr[y][x], arr[y][M - 1 - x]);
}
// 연산 3
void rotateRight() {
vector<vector<int>> tmp(M, vector<int>(N));
for (int y = N - 1; y >= 0; --y)
for (int x = 0; x < M; ++x)
tmp[x][N - 1 - y] = arr[y][x];
swap(N, M);
arr = tmp;
}
// 연산 4
void rotateLeft() {
vector<vector<int>> tmp(M, vector<int>(N));
for (int y = 0; y < N; ++y)
for (int x = 0; x < M; ++x)
tmp[M - 1 - x][y] = arr[y][x];
swap(N, M);
arr = tmp;
}
// 연산 5
void rotateGroupRight() {
vector<vector<int>> tmp(N, vector<int>(M));
int halfRow = N / 2, halfCol = M / 2;
for (int y = 0; y < halfRow; ++y)
for (int x = 0; x < halfCol; ++x)
tmp[y][x + halfCol] = arr[y][x]; // Group 1 to 2
for (int y = 0; y < halfRow; ++y)
for (int x = halfCol; x < M; ++x)
tmp[y + halfRow][x] = arr[y][x]; // Group 2 to 3
for (int y = halfRow; y < N; ++y)
for (int x = halfCol; x < M; ++x)
tmp[y][x - halfCol] = arr[y][x]; // Group 3 to 4
for (int y = halfRow; y < N; ++y)
for (int x = 0; x < halfCol; ++x)
tmp[y - halfRow][x] = arr[y][x]; // Group 4 to 1
arr = tmp;
}
// 연산 6
void rotateGroupLeft() {
vector<vector<int>> tmp(N, vector<int>(M));
int halfRow = N / 2, halfCol = M / 2;
for (int y = 0; y < halfRow; ++y)
for (int x = 0; x < halfCol; ++x)
tmp[y + halfRow][x] = arr[y][x]; // Group 1 to 4
for (int y = 0; y < halfRow; ++y)
for (int x = halfCol; x < M; ++x)
tmp[y][x - halfCol] = arr[y][x]; // Group 2 to 1
for (int y = halfRow; y < N; ++y)
for (int x = halfCol; x < M; ++x)
tmp[y - halfRow][x] = arr[y][x]; // Group 3 to 2
for (int y = halfRow; y < N; ++y)
for (int x = 0; x < halfCol; ++x)
tmp[y][x + halfCol] = arr[y][x]; // Group 4 to 3
arr = tmp;
}
void solve() {
for (int i = 0; i < R; ++i) {
switch(op[i]) {
case 1: flipHorizontal(); break;
case 2: flipvertical(); break;
case 3: rotateRight(); break;
case 4: rotateLeft(); break;
case 5: rotateGroupRight(); break;
case 6: rotateGroupLeft(); break;
}
}
}
void show() {
for (int y = 0; y < N; ++y) {
for (int x = 0; x < M; ++x)
cout << arr[y][x] << ' ';
cout << '\n';
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N >> M >> R;
arr = vector<vector<int>>(N, vector<int>(M));
for (int y = 0; y < N; ++y)
for (int x = 0; x < M; ++x)
cin >> arr[y][x];
for (int i = 0; i < R; ++i) cin >> op[i];
solve();
show();
}
'시뮬레이션' 유형에서 문제를 풀기 전부터 가장 효율적으로 풀이하는 방법부터 고민하는 것이 제 단점입니다.
(i.e. 배열 대입을 어떻게 가장 효율적으로 할 수 있을까, 공간복잡도를 줄일 수 있는 방법이 없을까 등)
앞으로 '시뮬레이션' 유형을 풀 때는 시간 내로 문제를 푸는 것에 집중해서 훈련해야겠습니다.