코딩테스트/BOJ

[BOJ] 17406 배열돌리기 4 - JAVA

5월._. 2022. 2. 12.
728x90

1. 문제

https://www.acmicpc.net/problem/17406

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net


2. 풀이

static 변수들

static int[][] deltas = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//오른쪽, 아래, 왼쪽, 위
static int N, M, K;	// 배열 크기, 회전 개수
static int[][] A;	//배열
static int MIN = Integer.MAX_VALUE;	//배열의 최소값 저장
static boolean[] isSelected;	//방문여부 저장 배열(회전 순서 정할 때 쓰임)
static int[][] numbers;	//회전 순서 저장 배열
static int[][] turns;	//입력받은 회전 정보 저장 배열

 

배열 깊은복사, 배열 최소값 계산

  • 원본 A를 보존해야하기 때문에 깊은 복사가 필요하다.
private static int[][] copyArray(){
    int[][] arr = new int[N][M];
    for(int k=0;k<A.length;k++){
        System.arraycopy(A[k],0,arr[k],0,A[k].length);
    }
    return arr;
}

private static int calcMin(int[][] arr){
    int min = Integer.MAX_VALUE;
    for (int i = 0; i < N; i++) {
        int sum = 0;
        for (int j = 0; j < M; j++) sum += arr[i][j];
        if (min > sum) min = sum;
    }
    return min;
}

 

회전 순서 정하기

  • K만큼 반복하면서 이미 선택된 회전이 아니라면 재귀로 방문한다(카운트+1). 방문이 끝나면 isSelected를 되돌려놓는다.
  • 카운트가 회전개수K와 동일하면 저장된 순서대로 회전하고, static MIN과 현재의 min을 비교해서 저장한다.
  • 회전하는 부분배열은 항상 한 변의 길이가 2*s인 정사각형이므로 회전 한 번 당 s번 만큼 turnArr배열을 호출한다.
private static void permutation(int cnt){
    if(cnt==K){
        //회전 다 하고 최소값비교
        int[][] arr = copyArray();
        for(int k=0;k<K;k++){
            for (int i = 0; ; i++) {
                //s만큼 반복하면 끝
                if (i >= numbers[k][2]) break;

                //회전하기
                arr = turnArr(arr, i, numbers[k][0], numbers[k][1], numbers[k][2]);
            }
        }

        MIN = Math.min(MIN,calcMin(arr));

        return;
    }

    for(int k=0;k<K;k++){
        if(isSelected[k]) continue;
        numbers[cnt] = turns[k];
        isSelected[k] = true;
        permutation(cnt+1);
        isSelected[k] = false;
    }
}

 

배열 회전

  • 회전할 배열arr, 몇 번째 껍질(?)인지i, 회전할 부분의 중심 인덱스(r,c), 중심에서 얼마나 멀어져야하는지s를 파라미터로 받는다. 방식은 2022.02.12 - [알고리즘/BOJ] - [BOJ] 16926 배열돌리기1 - JAVA 와 같다. 
  • 회전할 부분은 r-s부터 r+s, c-s부터 c+s이므로 i를 더하거나 빼준다. 
private static int[][] turnArr(int[][] arr, int i, int r, int c, int s) {
    int y = r - s + i;
    int x = c - s + i;
    int d = 0;

    int num = arr[y][x];

    while (true) {
        if (d == 4) break;

        int tmpy = y + deltas[d][0];
        int tmpx = x + deltas[d][1];

        if (tmpy < r - s + i|| tmpy > r + s - i|| tmpx < c - s + i|| tmpx > c + s - i) {
            ++d;
            continue;
        }

        int n = num;
        num = arr[tmpy][tmpx];
        arr[tmpy][tmpx] = n;

        y = tmpy;
        x = tmpx;

    }

    return arr;

}

 

메인 함수

public static void main(String[] args) throws Exception {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(in.readLine());

    N = Integer.parseInt(st.nextToken());
    M = Integer.parseInt(st.nextToken());
    K = Integer.parseInt(st.nextToken());

    A = new int[N][M];

    for (int i = 0; i < N; i++) {
        st = new StringTokenizer(in.readLine());
        for (int j = 0; j < M; j++) {
            A[i][j] = Integer.parseInt(st.nextToken());
        }
    }

    //회전 정보 저장
    turns = new int[K][3];
    for (int k = 0; k < K; k++) {
        st = new StringTokenizer(in.readLine());
        turns[k][0] = Integer.parseInt(st.nextToken())-1;
        turns[k][1] = Integer.parseInt(st.nextToken())-1;
        turns[k][2] = Integer.parseInt(st.nextToken());
    }

    //순서정하기
    isSelected = new boolean[K];
    numbers = new int[K][3];
    permutation(0);

    //최소값 출력
    System.out.println(MIN);
}

3. 결과

2022.02.12 - [알고리즘/BOJ] - [BOJ] 16935 배열돌리기 3 - JAVA처럼 순서대로 회전하면 되는 줄 알았다가 틀렸다. 그 다음에는 s만큼만 반복하면 되는데 r,c값과 비교하느라 배열 범위를 벗어났다. 

문제 자체를 이해하기는 어렵진 않았지만 그걸 구현하는 데 너무 많은 시간이 걸렸다.

 

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 2477 참외밭 - JAVA  (0) 2022.02.12
[BOJ] 2491 수열 - JAVA  (0) 2022.02.12
[BOJ] 16935 배열돌리기 3 - JAVA  (0) 2022.02.12
[BOJ] 16926 배열돌리기1 - JAVA  (0) 2022.02.12
[BOJ] 2563 색종이 - JAVA  (0) 2022.02.11

댓글