1. 문제
- 배열을 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
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 토마토 : 7569 : Java - BFS (S1) (2) | 2023.11.24 |
---|---|
[백준] 카잉 달력 : 6064 : Java - 브루트 포스 (S1) (1) | 2023.11.24 |
[백준] 가장 가까운 세 사람의 심리적 거리 : 20529 : Java - 완전 탐색(S1) (1) | 2023.11.22 |
[백준] 계단 오르기 : 2579 : Java - DP (S3) (0) | 2023.11.21 |
[백준] 케빈 베이컨의 6단계 법칙 : 1389 : Java - BFS (S1) (3) | 2023.11.21 |