문제 링크
주의사항
- JAVA를 사용하여 프로그램을 사용하였습니다.
- 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{
public static void main(String[] args){
}
}
문제 설명
접근 방법
이 문제를 풀기 전 아래 링크의 문제를 먼저 풀어오는 것을 추천드립니다.
이유는 이 문제에 대하여 설명할 때 회전하는 방법은 아래의 문제에서 다루었기 때문에 아래 링크의 문제와 이번 문제의 차이점을 다루며 설명할 것입니다.
아래 링크는 배열돌리기 1번에 대한 문제를 제가 해설한 내용입니다.
이 문제에 핵심은
1. 배열을 R번 돌린 배열 값들을 출력해야 합니다.
2. 배열을 회전할 때에는 반시계로 돌리며 각 범위별로 회전합니다.
사용되는 배열
arr[][] : 입력 배열을 저장하고 변경되어 결과로 출력되는 배열
문제 배열돌리기 1과 차이점은 회전하는 R의 값의 최대값이 매우 커졌다는 것입니다.
기존의 코드로 문제를 해결하려고 하면 시간초과가 무조건 발생할 수밖에 없습니다.
각 범위마다 회전할 때 처음 회전의 값으로 되돌아오는 것을 이용해야 합니다.
배열의 범위을 살펴보면
1 | 1 | 1 | 1 |
1 | 2 | 2 | 1 |
1 | 2 | 2 | 1 |
1 | 1 | 1 | 1 |
빨간색 범위에서는 12번을 회전하면 처음의 상태로 되돌아옵니다.
파란색 범위에서는 4번을 회전하면 처음의 상태로 되돌아옵니다.
처음으로 돌아오는 횟수를 이용하여 만약 빨간색이 50번을 회전한다면 2번 회전하는 경우와 같습니다.
50 % 12 = 2로 표현할 수 있기 때문입니다.
동일하게 파란색도 50번 회전하면
50 % 4 = 2로 2번 회전하는 경우와 같습니다.
이제 처음의 상태로 되돌아오는 횟수를 구하는 방법을 알아보면
범위의 크기가(N×M)인 경우 점화식은
(2*n) + (2*m) - 4 = 처음으로 돌아오는 회전 횟수
빨간색 범위일 때(4×4)
2*4 + 2*4 - 4 = 12
파란색 범위일 때(2×2)
2*2 + 2*2 - 4 = 4
각 범위별 (R%처음으로 돌아오는 회전 횟수)번을 회전을 진행한 뒤
배열의 값들을 저장한 뒤 최종적으로 만들어진 배열을 결과로 출력합니다.
문제를 해결한 알고리즘의 과정입니다.
1. 입력값 N×M 배열의 값과 R을 받습니다.
2. 배열의 각 범위마다 (R%원상태로 돌아오는 회전 횟수)번의 회전을 진행합니다.
3. 모든 회전이 끝난 뒤 배열에 값들을 결과로 출력합니다.
- BufferedReader를 사용하여 입력 값을 받았습니다.
- StringTokenizer를 이용하여 N×M배열과 N,M,R개의 연산을 나누었습니다.
- 각 범위별 (R%원상태로 돌아오는 회전횟수)번 배열을 회전하는 rotation함수를 만들었습니다.
- R번 rotation 함수를 실행시켜 회전합니다.
- BufferedWriter에 회전으로 변경된 최종 배열을 저장하였습니다
- BufferedWriter에 저장된 값을 결과로 출력하였습니다
- rotation함수는 구역을 나누어 값들을 회전하는 함수입니다.
결과 코드
import java.io.*;
import java.util.*;
public class Main {
static int[][] arr; //회전할 배열
static int N,M,R;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//입력값 처리하는 BufferedReader
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//결과값 출력하는 BufferedWriter
StringTokenizer st = new StringTokenizer(br.readLine()," ");
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());
int space = Math.min(N, M)/2; //공간 개수
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());
}
}
//기준
int n = N;
int m = M;
//크기
int width = N;
int weight = M;
for(int i=0;i<space;i++) {
rotation(i,n,m,width,weight);
//기준 감소
n-=1;
m-=1;
//크기 감소
width-=2;
weight-=2;
}
//회전한 후 배열값들 BufferedWriter 저장
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
bw.write(arr[i][j] + " ");
}
bw.newLine();
}
bw.flush(); //결과 출력
bw.close();
br.close();
}
//각 범위별 (R%원상태로 돌아오는 회전 횟수)번 회전하는 함수
static void rotation(int space, int n, int m, int width, int weight) {
int repeat = R % (width*2 + weight*2 - 4); //원상태로 돌아오는 회전 횟수
for(int i=0;i<repeat;i++) {
int temp = arr[space][space];
for(int j=space;j<m-1;j++) //←
arr[space][j] = arr[space][j+1];
for(int j=space;j<n-1;j++) //↑
arr[j][m-1] = arr[j+1][m-1];
for(int j=m-1;j>space;j--) //→
arr[n-1][j] = arr[n-1][j-1];
for(int j=n-1;j>space;j--) //↑
arr[j][space] = arr[j-1][space];
arr[space+1][space] = temp;
}
return;
}
}
'백준' 카테고리의 다른 글
[백준] code.plus(시뮬레이션과 구현,JAVA)14499번, 주사위 돌리기 (0) | 2022.05.09 |
---|---|
[백준] 단계별로 풀어보기(단계:12, 집합과 맵,JAVA)10815번, 숫자 카드 (0) | 2022.05.08 |
[백준] 단계별로 풀어보기(단계:27, 동적 계획법과 최단거리 역추적,JAVA)11779번, 최소비용 구하기 2 (0) | 2022.05.05 |
[백준] code.plus(시뮬레이션과 구현,JAVA)16926번, 배열 돌리기 1 (0) | 2022.05.05 |
[백준] 단계별로 풀어보기(단계:27, 동적 계획법과 최단거리 역추적,JAVA)9019번, DSLR (0) | 2022.05.03 |
댓글