백준 16926 - 배열 돌리기 1

Updated:

Java

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]
   ↓         ↓                   ↑         ↑
A[3][1]   A[3][2] → A[3][3] → A[3][4]   A[3][5]
   ↓                                       ↑
A[4][1] → A[4][2] → A[4][3] → A[4][4] → A[4][5]

예를 들어, 아래와 같은 배열을 2번 회전시키면 다음과 같이 변하게 된다.

1 2 3 4       2 3 4 8       3 4 8 6
5 6 7 8       1 7 7 6       2 7 8 2
9 8 7 6   →   5 6 8 2   →   1 7 6 3
5 4 3 2       9 5 4 3       5 9 5 4
 <시작>         <회전1>        <회전2>

배열과 정수 R이 주어졌을 때, 배열을 R번 회전시킨 결과를 구해보자.

접근 방법

주어진 연산에따라 배열의 값을 변화하였다.
4 X 4의 배열을 예로 들면,

[0,0] <- [0,1] / [0,1] <- [0,2] / [0,2] <- [0,3] : 우 [0,3] <- [1,3] / [1,3] <- [2,3] / [2,3] <- [3,3] : 하 [3,3] <- [3,2] / [3,2] <- [3,1] / [3,1] <- [3,0] : 좌 [3,0] <- [2,0] / [2,0] <- [1,0] / [1,0] <- [0,0] : 상
인 시계방향으로 값을 하나씩 차례로 대입시킨다.

또한 주목해야 할 것은, 문제 조건 중
min(N, M) mod 2 = 0이다.
이말은 즉, 행/열의 크기 중 작은 값은 항상 2의 배수라는 것이며, 위 조건이 있는 이유는

와 같이 3 x 4의 경우, 위 색칠 된 부분은 우하좌상의 방식으로 회전을 할 수 없다.
따라서 사전에 제약을 두어 위 경우는 생각하지 않아도 되게 하였다.

구현

전달 하려는 값을 시계방향으로 하나씩 이동하며 넣는다.
0,0을 미리 temp로 백업 시켜놓아, 마지막 대입인 [1,0] <- [0,0]를 가능하게 한다.
대입 하려는 값의 인덱스가 n X m의 범위를 벗어나면, 방향을 바꾸어 지속한다.
우 하 좌 상인 4 방향을 다 돌고 나면, 종료한다.

코드

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

public class Main {
	static int dy[] = {0,1,0,-1};		// 우, 하, 좌, 상 
	static int dx[] = {1,0,-1,0}; 
    public static void main(String []args) throws IOException {        
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer stk = new StringTokenizer(br.readLine());
    	int n = stoi(stk.nextToken());
    	int m = stoi(stk.nextToken());
    	int r = stoi(stk.nextToken());
    	int arr[][] = new int[n][m];
    	int sm = Math.min(n, m);
    	for(int i = 0; i < n; i++) {
    		stk = new StringTokenizer(br.readLine());
    		for(int j = 0; j < m; j++)
    			arr[i][j] = stoi(stk.nextToken());
    	}
    	int i, j, d = 0;
    	
    	while(r-- != 0) {		// 반복 횟수만큼 움직인다.
			for(int idx = 0; idx < sm/2; idx++) {
				i = idx;
				j = idx;
				d = 0;
				int tmp = arr[i][j];
				
				while(d != 4) {	
					// 만약 범위를 벗어나면, 대입하는 값의 방향을 바꾼다.
					if(i + dy[d] < idx || i + dy[d] >= n - idx  || j + dx[d] < idx || j + dx[d] >= m - idx) {		
						d++;		
						continue;
					}
					arr[i][j] = arr[i + dy[d]][j + dx[d]];
					i += dy[d];
					j += dx[d];
				}
				arr[idx + 1][idx] = tmp;
			}
    	}
    	
    	StringBuilder sb = new StringBuilder();
    	for(int[] a : arr) {
    		for(int v : a) {
    			sb.append(v).append(" ");
    		}
    		sb.append("\n");
    	}
    	System.out.println(sb.toString());
    	br.close();
    }
    static int stoi(String str) {
    	return Integer.parseInt(str);
    }
}

총평

난이도

⭐⭐★★★

후기

문제 조건인 행/열 최소 값은 2의 배수이다를 읽지 않아, 쓸데없이 고생했다.
문제를 잘 읽어라는 교수님 말씀이 뭔지 새삼 깨닫게된다 정말로,,

개선할 점

문제 좀 읽자!!!!