본문 바로가기
백준

[백준] code.plus(시뮬레이션과 구현,JAVA)16935번, 배열 돌리기 3

by 열정적인 이찬형 2022. 5. 2.

문제 링크

 

16935번: 배열 돌리기 3

크기가 N×M인 배열이 있을 때, 배열에 연산을 R번 적용하려고 한다. 연산은 총 6가지가 있다. 1번 연산은 배열을 상하 반전시키는 연산이다. 1 6 2 9 8 4 → 4 2 9 3 1 8 7 2 6 9 8 2 → 9 2 3 6 1 5 1 8 3 4 2 9 →

www.acmicpc.net


주의사항

  • JAVA를 사용하여 프로그램을 사용하였습니다.
  • 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{ 	
	public static void main(String[] args){
    }
}

문제 설명


접근 방법

이 문제에 핵심은

1. 주어진 배열을 문제에서 설명하는 6가지 방법으로 변경할 수 있도록 합니다.

2. R개의 변경이 끝난 뒤 배열을 결과로 출력합니다.

 

사용되는 배열

arr[][] : 입력 배열을 저장하고 변경되어 결과로 출력되는 배열

 

각 변경되는 명령어에 규칙을 찾아보면

 

1번 연산.

간단한 상하반전으로 배열의 값들을 변경해주면 됩니다.

 

2번 연산

간단한 좌우반전으로 배열의 값들을 변경해주면 됩니다.

 

3번 연산

오른쪽 90도 회전

회전 전

1(0,0) 2(0,1)
3(1,0) 4(1,1)
5(2,0) 6(2,1)

회전 후

5(0,0) 3(0,1) 1(0,2)
6(1,0) 4(1,1) 2(1,2)

1 : (0, 0) -> (0, 2)2 : (0, 1) -> (1, 2)3 : (1, 0) -> (0, 1)4 : (1, 1) -> (1, 1)5 : (2, 0) -> (0, 0)6 : (2, 1) -> (1, 0)

 

규칙은

(i, j) -> (j, 열 최대값 - i)

 

4번연산

왼쪽 90도 회전

회전 전

1(0,0) 2(0,1)
3(1,0) 4(1,1)
5(2,0) 6(2,1)

회전 후

2(0,0) 4(0,1) 6(0,2)
1(1,0) 3(1,1) 5(1,2)

1 : (0, 0) -> (1, 0)

2 : (0, 1) -> (0, 0)

3 : (1, 0) -> (1, 1)

4 : (1, 1) -> (0, 1)

5 : (2, 0) -> (1, 2)

6 : (2, 1) -> (0, 2)

 

규칙은

(i, j) -> (행 최대값-j, i)

 

5~6번에서는 배열을 4분면으로 나누어 값을 변경하는 것으로 아래와 같이 표현할 수 있습니다.

1(0,0) 1 2(0,2) 2
1 1 2 2
4(2,0) 4 3(2,2) 3
4 4 3 3

1사분면 시작값은 (0, 0)

2사분면 시작값은 (0, M/2)

3사분면 시작값은 (N/2, M/2)

4사분면 시작값은 (N/2, 0)

표현할 수 있습니다.

 

5번 연산

1사분면 -> 2사분면

2사분면 -> 3사분면

3사분면 -> 4사분면

4사분면 -> 1사분면

각 사분면 시작값을 기준으로 값을 변경해주면 됩니다.

만약 1사분면 -> 2사분면일 때

(0, 0) -> (0, N/2)처럼 옮기시면 됩니다.

 

6번 연산

1사분면 -> 4사분면

4사분면 -> 3사분면

3사분면 -> 2사분면

2사분면 -> 1사분면

각 사분면 시작값을 기준으로 값을 변경해주면 됩니다.

만약 1사분면 -> 4사분면

(0, 0) -> (N/2, 0)

 

문제를 해결한 알고리즘의 과정입니다.

1. 입력값 N×M 배열의 값과 R개의 연산을 받았습니다.

2. 각 연산의 규칙에 맞게 배열을 변경해줍니다.

3. 연산이 끝난 뒤 배열의 값들을 결과로 출력합니다.

 

  • BufferedReader를 사용하여 입력 값을 받았습니다.
  • StringTokenizer를 이용하여 N×M배열과 R개의 연산을 나누었습니다.
  • 각 연산에 맞게  upsideDown/reverseLeftAndRight/rightRotations/leftRotations/subarray_five/subarray_six 함수를 수행하였습니다.
  • 연산에 변경을 수행하는 change/subarrayChange/leftRotationsChange/rightRotationsChange 함수를 수행하였습니다.
  • BufferedWriter에 연산으로 변경된 최종 배열을 저장하였습니다.
  • BufferedWriter에 저장된 값을 결과로 출력하였습니다.
  • change함수는 3,4번 연산에 N과 M을 바꾸는 기능을 수행하였습니다.
  • subarrayChange함수는 5,6번 연산에 사분면을 바꾸는 기능을 수행하였습니다.
  • leftRotationsChange함수는 4번 연산에 값을 왼쪽 90도로 이동하는 기능을 수행하였습니다.
  • rightRotationsChange함수는 4번 연산에 값을 왼쪽 90도로 이동하는 기능을 수행하였습니다.

결과 코드

import java.io.*;
import java.util.*;
public class Main{
	static int[][] arr;	//입력되는 배열 저장
	static int N,M,R;
	public static void main(String[] arg) 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());
		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());
			}
		}
		st = new StringTokenizer(br.readLine()," ");
		for(int i=0;i<R;i++) {
			String command = st.nextToken();
			if(command.equals("1"))		//연산1.
				upsideDown();
			else if(command.equals("2"))	//연산2.
				reverseLeftAndRight();
			else if(command.equals("3")) 	//연산3.
				rightRotations();
			else if(command.equals("4"))	//연산4.
				leftRotations();
			else if(command.equals("5"))	//연산5
				subarray_five();
			else		//연산 6
				subarray_six();
		}
        	//배열 결과 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();
	}
    	//1번 연산 상하반전 수행
	static void upsideDown() {
		for(int i=0;i<N/2;i++) {
			for(int j=0;j<M;j++) {
				int temp = arr[N-1-i][j];
				arr[N-1-i][j] = arr[i][j];
				arr[i][j] = temp;
			}
		}
		return;
	}
   
    	//2번 연산 좌우 반전 수행
	static void reverseLeftAndRight() {
		for(int i=0;i<M/2;i++) {
			for(int j=0;j<N;j++) {
				int temp = arr[j][M-1-i];
				arr[j][M-1-i] = arr[j][i];
				arr[j][i] = temp;
			}
		}
		return;
	}
    	//3번 연산 오른쪽 90도 이동
	static void rightRotations() {
		change();
		int[][] result = new int[N][M];;
		rightRotationsChange(result, N, M);
		arr = new int[N][M];
		arr = result;
		return;
	}
    	//4번 연산 왼쪽 90도 이동
	static void leftRotations() {
		change();
		int[][] result = new int[N][M];
		leftRotationsChange(result, N, M);
		arr = new int[N][M];
		arr = result;
		return;
	}
    	//3번 연산에 값 변경하는 함수
	static void rightRotationsChange(int[][] temp, int row, int col) {
		for(int i=0;i<col;i++) {
			for(int j=0;j<row;j++) {
				temp[j][col-1-i] = arr[i][j];
			}
		}
		return;
	}
    	//4번 연산에 값 변경하는 함수
	static void leftRotationsChange(int[][] temp, int row, int col) {
		for(int i=0;i<col;i++) {
			for(int j=0;j<row;j++) {
				temp[row-1-j][i] = arr[i][j];
			}
		}
		return;
	}
    	//5번 연산 사분면 이동 수행
	static void subarray_five() {
		int[][] result = new int[N][M];
		subarrayChange(result, 0, 0, 0, M/2);
		subarrayChange(result, 0, M/2, N/2, M/2);
		subarrayChange(result, N/2, M/2, N/2, 0);
		subarrayChange(result, N/2, 0, 0, 0);
		arr = result;
		return;
	}
    	//6번 연산 사분면 이동 수행
	static void subarray_six() {
		int[][] result = new int[N][M];
		subarrayChange(result, 0, 0, N/2, 0);
		subarrayChange(result, N/2, 0, N/2, M/2);
		subarrayChange(result, N/2, M/2, 0, M/2);
		subarrayChange(result, 0, M/2, 0, 0);
		arr = result;
		return;
	}
    	//5,6번 사분면 배열 변경하는 함수
	static void subarrayChange(int[][] temp, int x1, int y1, int x2, int y2) {
		for(int i=0;i<N/2;i++) {
			for(int j=0;j<M/2;j++) {
				temp[x2+i][y2+j] = arr[x1+i][y1+j];
			}
		}
		return;
	}
    	//N,M을 변경하는 함수
	static void change() {
		int temp = N;
		N = M;
		M = temp;
		return;
	}
}

댓글