문제 링크

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

풀이

  • 테두리 단위로 배열을 돌리기 위해 큐를 사용했다. 정확히는 원형 큐의 방식을 차용해서 배열 값을 순환할 수 있도록 했다.
  • 문제는 테두리의 개수를 정하는 과정에 있었는데, 문제의 조건 중 하나가 배열의 행 n과 열 m 중 작은 값은 무조건 짝수라는 점을 간과했다. (min(N, M) mod 2 = 0) 이를 통해 배열의 테두리 개수는 nm 중 더 작은 값을 2로 나눈 것과 같다. 하지만 이를 알아채지 못하고 테두리의 개수를 n/2로 고정해버려서 계속 오답 처리가 되었다.
  • 각 테두리의 좌측 상단부터 시계 방향으로 값을 큐에 담고, r만큼 맨 앞의 값을 뽑고 다시 맨 뒤에 넣는 것을 반복했다. 그리고 다시 좌측 상단부터 시계 방향으로 큐의 값을 하나씩 뽑아서 배열에 저장했다.
  • 큐를 사용하는 대신 각 테두리의 좌측 상단을 임시로 저장하고 시계 방향으로 모든 요소를 한 칸씩 당긴 다음, 저장한 값을 처음 위치의 바로 아래 행에 저장하는 방법도 있다. 시간 상 따로 구현하지는 않았다.
소스 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

/**
 * 백준 16926번: 배열 돌리기 1
 */
public class Main {
    private static int[][] arr;
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        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[] dr = {0, 1, 0, -1};
        int[] dc = {1, 0, -1, 0};
        
        // 배열 초기화
        arr = new int[n][m];
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < m; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }
      
        // 배열의 현재 테두리의 모든 원소를 담기 위한 큐 생성
        Queue<Integer> queue = new LinkedList<>();
        
        // 테두리의 개수는 n과 m 중 더 작은 값을 2로 나눈 것과 같음
        for (int i = 0; i < Math.min(n, m) / 2; i++) {
            // 좌측 상단부터 시계 방향으로 큐에 삽입
            int row = i, col = i, dir = 0;
            for (int j = 0; j < (n+m-4*i-2)*2; j++) {
                queue.offer(arr[row][col]);
                
                row += dr[dir];
                col += dc[dir];
                
                if (dir == 0 && col + 1 >= m - i) dir = ++dir % 4;
                else if (dir == 1 && row + 1 >= n - i) dir = ++dir % 4;
                else if (dir == 2 && col - 1 < i) dir = ++dir % 4;
                else if (dir == 3 && row - 1 < i) dir = ++dir % 4;
            }

            // 맨 앞 원소를 r번 뽑아서 다시 큐에 삽입
            for (int j = 0; j < r; j++) queue.offer(queue.poll());
            
            // 다시 좌측 상단부터 시계 방향으로 배열에 입력
            row = i;
            col = i;
            dir = 0;
            for (int j = 0; j < (n+m-4*i-2)*2; j++) {
                arr[row][col] = queue.poll();
                
                row += dr[dir];
                col += dc[dir];
              
                if (dir == 0 && col + 1 >= m - i) dir = ++dir % 4;
                else if (dir == 1 && row + 1 >= n - i) dir = ++dir % 4;
                else if (dir == 2 && col - 1 < i) dir = ++dir % 4;
                else if (dir == 3 && row - 1 < i) dir = ++dir % 4;
            }
            
            queue.clear();
        }
      
        // 배열 출력
        printArray();
        br.close();
    }
    
    public static void printArray() {
        StringBuilder sb = new StringBuilder();
        StringBuilder row;
        
        for (int i = 0; i < arr.length; i++) {
            row = new StringBuilder();
            for (int j = 0; j < arr[i].length; j++) {
                row.append(arr[i][j] + " ");
            }
            row.setLength(row.length() - 1);
            sb.append(row + "\n");
        }
        
        System.out.print(sb.toString());
    }
}