일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 스프링
- 골드3
- 알고리즘
- 중복순열
- Spring
- professional
- D4
- 트리의지름
- SW역량테스트
- 최단경로
- java
- swea
- 백엔드
- Floyd
- 그래프
- SW역량평가
- backend
- 실버1
- 백준
- 최단경로탐색
- Framework
- 골드5
- dp
- 최소신장트리
- 순열
- BOJ
- 1251
- 완전탐색
- BFS
- 코딩테스트
- Today
- Total
공부 기록장
[백준-16926] 배열돌리기 본문
이 문제는 백준에 있는 SILVER 3 단계 문제이다.
이 문제는 주어진 배열을 돌리면 되는 문제인데, 예제를 참고하면 더 쉽게 이해할 수 있다.
배열의 크기인 N과 M이 주어지고 몇 번 돌리면 되는지가 주어진 후에 배열의 모양이 주어진다.
1 | 1 | 1 | 1 |
1 | 2 | 2 | 1 |
1 | 2 | 2 | 1 |
1 | 1 | 1 | 1 |
1번은 1번끼리, 2번은 2번끼리 돌아간다고 생각하면 된다.
이 문제에서는 while문 돌리기가 핵심이었다.
아래, 왼쪽, 위, 오른쪽 순서대로 for문을 돌려 인덱스를 계산 해 주었다.
idx는 행의 번호를 뜻하는데 제한 조건에서 N과 M 중 작은것은 무조건 짝수라고 했으므로 N과 M중 작은 수의 반까지만 가게 설정해 주었다. 만약 0행부터 3행까지 있다면 0행-3행, 1행-2행은 같이 움직이기 때문에 idx를 끝까지 계산해주면 값이 틀려지기 때문이다.
처음에는 배열을 하나만 이용해서 짜 보려고 했는데 값이 잘 나오지 않아서 배열 두 개를 활용했다. cnt는 밑에서 증가시켜주기 때문에 홀수번 째 도는거라면 arr에 있는 값을 돌린 뒤 ans에 넣어주었고, 짝수번 째 도는거라면 ans에 저장 된 값을 arr에 넣어 주었다.
while(cnt != R) {
int row = 0;
int col = 0;
int idx = 0;
int Nlen = N-1; //가로 길이
int Mlen = M-1; //세로 길이
if(cnt%2 == 0) {
while(idx < Math.min(M,N)/2) {
for(int i=N-Nlen-1; i<Nlen; i++) { //아래로 가기
ans[i+1][col] = arr[i][col];
row = i+1;
}
for(int i=M-Mlen-1; i<Mlen; i++) {//왼쪽으로 가기
ans[row][i+1] = arr[row][i];
col = i+1;
}
for(int i=N-Nlen-1; i<Nlen; i++) {//위로 가기
ans[i][col] = arr[i+1][col];
row=idx;
}
idx++;
for(int i=M-Mlen-1; i<Mlen; i++) { //오른쪽으로 가기
ans[row][i] = arr[row][i+1];
col = idx;
}
Nlen--;
Mlen--;
}
cnt++;
}
else {
while(idx < Math.min(M,N)/2) {
for(int i=N-Nlen-1; i<Nlen; i++) { //아래로 가기
arr[i+1][col] = ans[i][col];
row = i+1;
}
for(int i=M-Mlen-1; i<Mlen; i++) {//왼쪽으로 가기
arr[row][i+1] = ans[row][i];
col = i+1;
}
for(int i=N-Nlen-1; i<Nlen; i++) {//위로 가기
arr[i][col] = ans[i+1][col];
row=idx;
}
idx++;
for(int i=M-Mlen-1; i<Mlen; i++) { //오른쪽으로 가기
arr[row][i] = ans[row][i+1];
col = idx;
}
Nlen--;
Mlen--;
}
cnt++;
}
}
전체 코드는 저 핵심 부분에서 입력과 출력만 추가되었을 뿐, 나머지는 같다.
이 문제는 코드를 다 짜놓고 제한 조건을 제대로 보지 않아서 고생했다. 제한 조건을 보면 무조건 하나는 짝수가 들어온다고 쓰여 있는데 홀*홀의 경우처럼 필요 없는 것들을 만들다가 인덱스 계산을 틀렸었다.
또, 배열을 하나만 사용하면 메모리를 절약할 수 있을 것 같은데 방법을 잘 모르겠다. 다른 솔루션을 좀 더 찾아봐야겠다.
import java.util.Scanner;
public class 배열돌리기_16926 {
static int[][] arr;
static int[][] ans;
static int N;
static int M;
static int R;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
M = sc.nextInt();
R = sc.nextInt();
arr = new int[N][M];
ans = new int[N][M];
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) {
arr[i][j] = sc.nextInt();
}
}
int cnt = 0;
while(cnt != R) {
int row = 0;
int col = 0;
int idx = 0;
int Nlen = N-1; //가로 길이
int Mlen = M-1; //세로 길이
if(cnt%2 == 0) {
while(idx < Math.min(M,N)/2) {
for(int i=N-Nlen-1; i<Nlen; i++) { //아래로 가기
ans[i+1][col] = arr[i][col];
row = i+1;
}
for(int i=M-Mlen-1; i<Mlen; i++) {//왼쪽으로 가기
ans[row][i+1] = arr[row][i];
col = i+1;
}
for(int i=N-Nlen-1; i<Nlen; i++) {//위로 가기
ans[i][col] = arr[i+1][col];
row=idx;
}
idx++;
for(int i=M-Mlen-1; i<Mlen; i++) { //오른쪽으로 가기
ans[row][i] = arr[row][i+1];
col = idx;
}
Nlen--;
Mlen--;
}
cnt++;
}
else {
while(idx < Math.min(M,N)/2) {
for(int i=N-Nlen-1; i<Nlen; i++) { //아래로 가기
arr[i+1][col] = ans[i][col];
row = i+1;
}
for(int i=M-Mlen-1; i<Mlen; i++) {//왼쪽으로 가기
arr[row][i+1] = ans[row][i];
col = i+1;
}
for(int i=N-Nlen-1; i<Nlen; i++) {//위로 가기
arr[i][col] = ans[i+1][col];
row=idx;
}
idx++;
for(int i=M-Mlen-1; i<Mlen; i++) { //오른쪽으로 가기
arr[row][i] = ans[row][i+1];
col = idx;
}
Nlen--;
Mlen--;
}
cnt++;
}
}
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) {
if(R%2 == 0)
System.out.print(arr[i][j]+" ");
else {
System.out.print(ans[i][j]+" ");
}
}
System.out.println();
}
}
}