import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int[][] map;
static int N, M, R;
static int[] x = new int[]{0, 1, 0, -1};
static int[] y = new int[]{1, 0, -1, 0};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());
map = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
start();
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
System.out.print(map[i][j]+" ");
}
System.out.println();
}
}
public static void start() {
for (int i = 0; i < R ; i++) {
boolean[][] check = new boolean[N][M];
int[][] newArr = new int[N][M];
rotate(check, newArr);
map = newArr;
}
}
private static void rotate(boolean[][] check, int[][] newArr) {
for (int i = 0, j = 0; i < N && j < M; i++, j++) {
if (!check[i][j]) {
int cx = j;
int cy = i;
for (int k = 0; k < 4; k++) {
int px = x[k];
int py = y[k];
while (cx+px >= 0 && cx+px < M && cy+py >= 0 && cy+py < N && !check[cy+py][cx+px]){
newArr[cy+py][cx+px]=map[cy][cx];
check[cy+py][cx+px]=true;
cy = cy+py;
cx = cx+px;
}
}
}
}
}
}
😰처음에는 같은 크기의 배열을 만들어서 이미 방문한 곳은 방문하지 못하게 처리하였으며 또한 이동한 값을 다시 옮겨주는 작업으로 처리하였습니다.
rotate의 경우에는 지난 간 곳이 아니라면 x,y 배열에서 정의한 대로 (실제 백준 사이트의 그림처럼) 직접 하나씩 옮겨가며 계산하였습니다.그러나 위 방식대로 하면 메모리를 엄청나게 잡아먹는다는 단점이 있기에 다른 고민하고 찾아보았습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int[][] map;
static int N, M, R;
static int[] y = new int[]{0, 1, 0, -1};
static int[] x = new int[]{1, 0, -1, 0};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());
map = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
int group = Math.min(N, M) / 2;
rotate(group);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
private static void rotate(int group) {
for (int k = 0; k < R; k++) {
for (int i = 0; i < group; i++) {
int cx = i;
int cy = i;
int lastValue = map[cy][cx];
int direct = 0;
while (direct < 4) {
int px = cx + x[direct];
int py = cy + y[direct];
if (px >= i && px < M-i && py >= i && py < N-i) {
map[cy][cx] = map[py][px];
cx = px;
cy = py;
} else {
direct++;
}
}
map[cy+1][cx] = lastValue;
}
}
}
}
🤔첫 번째 방식과 비교하여 메모리 사용량을 대폭 줄일 수 있었습니다.(시간도 확연히 줄었습니다.)
배열을 생성하지 않고 기존 배열을 이용하여 푸는 방식으로
백준에서 설명하는 그림처럼 이동하며 푼다기보다는 반대로 움직이면서 풀이 한 것을 확인 할 수 있습니다.