차곡차곡 성 쌓기
article thumbnail

1. 문제

 

16926번: 배열 돌리기 1

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

 

  • 배열을 R번 회전 후 결과를 출력한다.
  • 안쪽에서 회전이 안일어나는 경우는 가로나 세로의 크기 2보다 작을 때이다.

 

2.  풀이 생각

처음 봤을 때는 저번에 풀었던 달팽이 게임(참고: https://uzinlab.tistory.com/52 ) 문제랑 비슷해서, 전체적인 틀은 네 방향을 나눠서 각각 구현하기로 생각하였고, 구현 문제답게 코드를 짜기전에 열심히 구상을 하고 코드를 짜기로 헀다!

 

하지만 어떠한 방식으로 화전하냐? 봤을 때 한 번의 회전이 전체 요소에 이어져서 일어나는 것이 아니라, 테두리별로 일어나는 것이었다. 그래서 테두리 별로 회전하는 작업을 바깥 테두리부터 안쪽 테두리로 이동하며 반복하기로 했다.

 

한 번의 회전을 그만두는 조건은 회전할 가로나 세로의 크기가 2보다 작으면 그만둔다. 이때 한 번의 회전 작업이 끝나고 이를 입력받는 `R`번 반복한다.

 

 

3. 로직

배열에 한 번의 회전 작업이 일어나면 (1,1)부터 회전을 시작한다.

 

반시계 방향을 `dx`, `dy`로 설정하고 `direction`에 따라 좌표 이동을 진행한다. 좌표를 이동 후 직전 좌표의 요소인 `preValue`로 현재 요소를 이전 요소로 바꾼다. 변경 작업이 일어날 때마다 `count`를 1 증가시키고, count가 가로-1 , 세로 -1 크기보다 커지만 방향을 전환한다. 

        int dx[] = {0,1,0,-1};
        int dy[] = {1,0,-1,0};
        int direction = 0;

	// 한 번 회전 - 바깥 영역 부터 안쪽 영역으로 이동
            while(row >=2 && col>=2){
                int count= 0;
                int start = startIndex++;
                int x = start;
                int y = start;
                int preValue = array[start][start];

                // 시작 위치로 다시 돌아올 때까지 반복
                do{
                    x = x + dx[direction];
                    y = y + dy[direction];

                    int temp = array[y][x];
                    array[y][x] = preValue; // 전진한 좌표 갱신
                    preValue = temp;

                    count++;

                    // 세로 방향일 때
                    if(direction == 0 || direction == 2){
                        if(count == row-1){
                            direction= (direction+1)%4;
                            count =0;
                        }

                    // 가로 방향일 때
                    } else{
                        if(count == col-1){
                            direction= (direction+1)%4;
                            count =0;
                        }
                    }
                // 처음 위치로 돌아오기 전까지 이동
                }while(x!= start || y!= start);

 

 

 

4 전체 코드

import java.io.*;
import java.util.*;

public class Main {


    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int R = Integer.parseInt(st.nextToken());

        // 배열 입력 받기
        int [][] array = new int[N+2][M+2];
        for(int i=1; i<=N; i++){
            st = new StringTokenizer(br.readLine());
            for(int j=1; j<=M; j++){
                array[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        int dx[] = {0,1,0,-1};
        int dy[] = {1,0,-1,0};

        // R번만큼 돌리기
        for(int r=0; r<R; r++){
            int row = N;
            int col = M;
            int direction = 0;
            int startIndex = 1;

            // 한 번 회전 - 바깥 영역 부터 안쪽 영역으로 이동
            while(row >=2 && col>=2){
                int count= 0;
                int start = startIndex++;
                int x = start;
                int y = start;
                int preValue = array[start][start];

                // 시작 위치로 다시 돌아올 때까지 반복
                do{
                    x = x + dx[direction];
                    y = y + dy[direction];

                    int temp = array[y][x];
                    array[y][x] = preValue; // 전진한 좌표 갱신
                    preValue = temp;

                    count++;

                    // 세로 방향일 때
                    if(direction == 0 || direction == 2){
                        if(count == row-1){
                            direction= (direction+1)%4;
                            count =0;
                        }

                    // 가로 방향일 때
                    } else{
                        if(count == col-1){
                            direction= (direction+1)%4;
                            count =0;
                        }
                    }
                // 처음 위치로 돌아오기 전까지 이동
                }while(x!= start || y!= start);

                row -= 2;
                col -= 2;
            }
        }

        //출력
        for(int i=1; i<=N; i++){
            for(int j = 1;j<=M; j++){
                bw.write(array[i][j] +" ");

            }
            bw.write("\n");
        }


        bw.flush();

        bw.close();
        br.close();
    }


}
728x90
profile

차곡차곡 성 쌓기

@nagrang

포스팅이 좋았다면 "좋아요" 해주세요!