본문 바로가기
백준/구현

백준 16927 c++ "배열 돌리기 2" -PlusUltraCode-

by PlusUltraCode 2025. 9. 27.

https://www.acmicpc.net/problem/16927

[필자 사고]

재미난 문제다.

필자는 달팽이 문제에 약했따.

ㅇㅣ 문제를 풀면서 어느정도 감을 익힐 수 있었다. 

달팽이 문제의 핵심은 layer를 만드는 일이다. 

layer 만드는 공식은 min(N,M)/2 를 하게 되면 총 layer갯수를 구할 수 있다. 

layer 별로 회전을 진행한다. 

height 및 width 의 크기를 구한뒤 주기를 구할 수 있고 그로인해 중복되는 회전을 막을 수 있다.

Rotate() 함수를 살펴보자. 

layer와 회전수와 관련된 매개변수를 받은 뒤 

top, bottom, left , right 의 열과 행들을 입력받은다. 

그 다음 4개의 for문을 이용하여 회전을 진행해준다. 

마지막에 temp값은 반드시 넣어주자. 반시계나 시계방향 회전에 따라 달라질 수 있음 유도리있게 

 

아래는 자세한 코드 해설이다.

[코드 해설]

Input()

  • 사용자 입력을 받아서 N(행), M(열), R(회전 횟수)을 저장한다.
  • arr 2차원 벡터를 N × M 크기로 초기화한 뒤, 행렬의 각 원소를 입력받아 저장한다.

RotateLayer(int layer, int count)

  • 하나의 레이어(테두리)를 count번 반시계 방향으로 회전시키는 함수.
  • top, left, bottom, right는 현재 레이어의 경계 인덱스다.
  • 회전은 다음 순서로 진행된다:
    1. arr[top][left] 값을 first에 저장한다. (맨 앞 원소 보존)
    2. 위쪽 행의 원소들을 왼쪽으로 한 칸씩 이동시킨다.
    3. 오른쪽 열의 원소들을 위쪽으로 한 칸씩 이동시킨다.
    4. 아래쪽 행의 원소들을 오른쪽으로 한 칸씩 이동시킨다.
    5. 왼쪽 열의 원소들을 아래쪽으로 한 칸씩 이동시킨다.
    6. 처음 저장한 first 값을 arr[top+1][left] 위치에 넣어서 순환을 완성한다.

RotateCounterClockWise()

  • 배열 전체를 반시계 방향으로 회전시키는 함수.
  • 배열은 여러 겹의 레이어(테두리)로 구성되므로, min(N, M) / 2만큼의 레이어가 생긴다.
  • 각 레이어마다:
    1. 레이어의 높이(height)와 너비(width)를 계산한다.
    2. 둘레의 길이(parameter = 2*(height+width)-4)를 구한다.
    3. 실제로 필요한 회전 횟수(R % parameter)를 구한다.
    4. RotateLayer를 호출하여 해당 레이어를 회전시킨다.

Print()

  • 현재 arr 배열의 상태를 행렬 형태로 출력한다.
  • 각 행마다 원소를 공백으로 구분하여 출력하고, 줄바꿈을 수행한다.

Game_Start()

  • 배열 회전의 전체 흐름을 관리하는 함수.
  • RotateCounterClockWise()를 호출하여 배열을 회전시킨 뒤,
  • 최종 결과를 Print()를 통해 출력한다.

main()

  • 입출력 속도를 빠르게 하기 위해 ios::sync_with_stdio(false)와 cin.tie(nullptr)을 설정한다.
  • Input()으로 데이터를 입력받고, Game_Start()를 호출하여 프로그램을 실행한다.

[소스 코드]

#include <iostream>
#include <vector>
using namespace std;

int N, M, R;
vector<vector<int>> arr;

void Input() {
    cin >> N >> M >> R;
    arr.assign(N, vector<int>(M));
    for (int i = 0; i < N; i++) {
        for (int k = 0; k < M; k++) {
            cin >> arr[i][k];
        }
    }
}

void RotateLayer(int layer, int count) {
    int top = layer;
    int left = layer;
    int bottom = N - layer - 1;
    int right = M - layer - 1;

    for (int r = 0; r < count; r++) {
        int first = arr[top][left];

        for (int j = left; j < right; j++) {
            arr[top][j] = arr[top][j + 1];
        }

        for (int j = top; j < bottom; j++) {
            arr[j ][right] = arr[j+1][right];
        }
        for (int j = right; j > left; j--) {
            arr[bottom][j] = arr[bottom][j - 1];
        }

        for (int j = bottom; j > top; j--) {
            arr[j][left] = arr[j-1][left];
        }

        arr[top+1][left] = first;
    }
}

void RotateCounterClockWise() {
    int layer = min(N, M) / 2;
    
    for (int i = 0; i < layer; i++) {
        int height = N - 2 * i;
        int width = M - 2 * i;
        int parameter = 2 * (height + width) - 4;

        int rotateCount = R % parameter;
        RotateLayer(i, rotateCount);
    }
}

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

void Game_Start() {
    RotateCounterClockWise(); // 최적화된 회전
    Print();
}

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

    Input();
    Game_Start();
}