공부 기록장

[백준-16926] 배열돌리기 본문

카테고리 없음

[백준-16926] 배열돌리기

또도닝 2021. 2. 19. 17:24

이 문제는 백준에 있는 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();
		}
	}
}

 

Comments