Algorithm/백준과 프로그래머스

[C++] 16926. 배열 돌리기1

young_3060 2024. 3. 11. 15:23
728x90

 

 

아.. 인덱스가 너무 헷갈리고 회전 레이어 다루는게 어려워서 어려운 문제가 아니었는데도 좀 고전했다..

다시 풀어봐야할 것 같다ㅜㅠ (확실히 구현에 좀 약한듯..)

 

우선, 회전 레이어 갯수는 N 또는 M 중 작은 값을 2로 나눈 값과 같다.

시작점은 (0,0), (1,1) ...로 되므로 이를 이용하여 시작점을 잡아주면 된다.

 

우선, 회전하는 방법을 잘 생각해야 하는데, 시작점을 0,0으로 잡았기 때문에 이를 temp 변수에 넣어주고 시작점부터 채워주기 시작한다.

 

[ 시작점부터 채우는 방향 ]

  1. 맨 윗줄 : 오 -> 왼 방향으로 채워준다
  2. 가장 오른쪽 열 : 아래 -> 위 방향으로 채워준다
  3. 맨 아랫줄 : 왼 -> 오 방향으로 채워준다
  4. 가장 왼쪽 열 : 위 -> 아래 방향으로 채워준다.

이 과정을 각 레이어마다 반복해주면 되는데, 그건 그냥 시작점, 끝점만 변경해주면 된다.

 

차례대로 코드를 살펴보자.

<편의상 가정>

- 현재 레이어는 0, 즉 가장 바깥 배열층을 돌리는 과정을 예시로 들겠다

- i는 행, 최댓값이 N이다.

- j는 열, 최댓값이 M이다.

 

 

1️⃣ 맨 윗줄 : 오 -> 왼 방향으로 채워준다

i는 0으로 고정, j만 차례대로 움직인다.

j는 0부터 시작해서 M-1전까지 증가한다.

바로 오른쪽 값을 왼쪽에 채워넣기 때문에 j+1인 값을 j에 넣어준다.

//i = 0
//j = 0 ~ M-1

arr[0][j] = arr[0][j+1]

 

 

2️⃣ 가장 오른쪽 열 : 아래 -> 위 방향으로 채워준다

이번엔 j가 최대값으로 고정, i만 차례대로 움직인다.

i는 0부터 시작해서 N-1전까지 증가한다.

바로 아래쪽 값을 위에 채워넣기 때문에 i+1인 값을 i에 넣어준다.

//i = 0 ~ N-1
//j = M-1

arr[i][j] = arr[i+1][j]

 

 

3️⃣ 맨 아랫줄 : 왼 -> 오 방향으로 채워준다

이번엔 i가 최대값으로 고정, j만 차례대로 움직인다.

j는 왼쪽값을 오른쪽에 넣어주기 때문에 최댓값부터 시작하고 점점 줄여나간다.

따라서 j값의 범위는 M-1부터 0 직전까지이다.

//i = N-1
//j = M-1 ~ 0

arr[i][j] = arr[i][j-1]

 

 

4️⃣ 가장 왼쪽 열 : 위 -> 아래 방향으로 채워준다.

이번엔 j는 다시 0으로 고정, i값만 차례대로 움직인다.

이전 i값을 넣어주기때문에 3번과 마찬가지로 최댓값부터 시작하고 점점 줄여나간다.

범위는 N-1부터 0직전까지이다.

//i = N-1 ~ 0
//j = 0

arr[i][j] = arr[i-1][j]

 

 

📌 각 (i, j의) 최댓값은 코드에서 iEdge, jEdge로 표현했으며 레이어를 반영해주기 위해 -layer한다.

📌 마지막 비워진 칸에는 temp에 저장해놓은 시작점을 넣어준다.

📌 마지막 비워진 칸은 시작점의 바로 밑 칸이기 때문에 arr[layer+1][layer]가 된다.

 

 

< 코드 >

#include <iostream>
using namespace std;

/*
<문제 정리>
크기 N*M 배열 반시계로 회전 -> R번 회전시킨 결과 출력
*/

#define MAX 301
int arr[MAX][MAX];
int N, M, R;

void rotation(int layer)
{

    int temp = arr[layer][layer];
    int iEdge = N-layer-1, jEdge = M-layer-1;
    // 오->왼, 아->위, 왼->오, 위->아 순서대로 진행
    // layer = circle

    // 오른쪽에서 왼쪽으로 채우기
    for (int j = layer; j < jEdge; j++)
        arr[layer][j] = arr[layer][j+1];

    // 아래쪽에서 위쪽으로 채우기
    for(int i=layer; i<iEdge; i++)
        arr[i][jEdge] = arr[i+1][jEdge];

    // 왼쪽에서 오른쪽으로 채우기
    for(int j=jEdge; j>layer; j--)
        arr[iEdge][j] = arr[iEdge][j - 1];

    // 위쪽에서 아래쪽으로 채우기
    for(int i=iEdge; i>layer; i--)
        arr[i][layer] = arr[i-1][layer];

    // 마지막 비워진 칸에 temp 넣기
    arr[layer+1][layer] = temp;
}

int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin >> N >> M >> R;

    for(int i=0; i<N; i++) {
        for(int j=0; j<M; j++) {
            cin >> arr[i][j];
        }
    }

    int layers = min(N, M) / 2;

    for(int i=0; i<R; i++) {
        for(int layer=0; layer<layers; layer++) rotation(layer);
    }

    for(int i=0; i<N; i++) {
        for(int j=0; j<M; j++) {
            cout << arr[i][j] << " ";
        }
        cout << '\n';
    }

    return 0;
}
728x90