CodingTest

백 준 - 14500

electronicprogrammer 2020. 11. 2. 04:20

문제 : www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

 

문제는 다음과 같습니다.

 

문제에서 요구하는 것은 주어진 배열에서 어떠한 테트로미노를 1개만 설치하였을 때 가장 큰 값을 가지는가 입니다.

 

먼저 모든 테트로미노를 좌우 및 상하로 회전한 모든 경우를 배열에서 검사하기에는 코드가 너무 복잡하고 힘들 것 같습니다.

여기서 아래의 테트로미노를 제외하면 

 

테트로미노를 상하좌우 회전 및 뒤집은 경우를 생각하면 그냥 상, 하 , 좌 , 우 로 1칸씩 이동하는 모든 경우가 가능하다라는 것을 알 수 있습니다.

 

그래서 이를 제귀로 구현하고 위에서의 예외는 따로 처리해주도록 하겠습니다.

전체적인 코드는 다음과 같습니다.

import java.util.*;

public class Main {

    // 문제 14500

    public static int[][] arr;
    public static int maxValue = -1;
    public static int[] dx = new int[]{0 , 0 , 1, -1};
    public static int[] dy = new int[]{1 , -1 , 0, 0};

    public static void main(String[] args) {

        Scanner stdin = new Scanner(System.in);

        int n = stdin.nextInt();
        int m = stdin.nextInt();

        arr = new int[n][m];
        boolean[][] flag = new boolean[n][m];

        for (int i = 0 ; i < n ; i++) {

            for(int j = 0 ; j < m ; j++) {

                arr[i][j] = stdin.nextInt();
            }
        }

        for(int i = 0 ; i < arr.length ; i++) {

            for(int j = 0 ; j < arr[0].length ; j++) {

                flag[i][j] = true;

                move(j , i , arr[i][j] , 0 , flag);

                flag[i][j] = false;
            }
        }

        maxValue = Math.max(maxValue , searchExcept1());
        maxValue = Math.max(maxValue , searchExcept2());
        maxValue = Math.max(maxValue , searchExcept3());
        maxValue = Math.max(maxValue , searchExcept4());

        System.out.println(maxValue);
    }


    //중복이 있어서는 안된다
    public static void move(int x, int y , int value , int idx , boolean[][] flag) {

        // 4칸 모두 움직임
        if (idx == 3) {

            maxValue = Math.max(maxValue , value);

            return;
        }

        for (int i = 0 ; i < 4 ; i++) {

            int nextY = y + dy[i];
            int nextX = x + dx[i];

            if ((nextY < arr.length && nextY >= 0 ) && (nextX < arr[0].length && nextX >= 0) ) {

                if (flag[nextY][nextX] == false) {

                    flag[nextY][nextX] = true;

                    // 4방향 중에서 1방향으로 움직임
                    move(nextX , nextY , value + arr[nextY][nextX] , idx+1 , flag);

                    flag[nextY][nextX] = false;

                }
            }


        }

    }

    public static int searchExcept1() {

        int max_Val = 0;

        for (int i = 0 ; i < arr.length-1 ; i++) {

            for(int j = 0 ; j < arr[0].length - 2 ; j++) {

                int val = arr[i][j] + arr[i][j+1] + arr[i+1][j+1]+ arr[i][j+2];

                max_Val = Math.max(max_Val , val);
            }
        }

        return max_Val;
    }

    public static int searchExcept2() {

        int max_Val = 0;

        for (int i = 1 ; i < arr.length ; i++) {

            for(int j = 0 ; j < arr[0].length - 2 ; j++) {

                int val = arr[i][j] + arr[i][j+1] + arr[i-1][j+1]+ arr[i][j+2];

                max_Val = Math.max(max_Val , val);
            }
        }

        return max_Val;
    }

    public static int searchExcept3() {

        int max_Val = 0;

        for (int i = 0 ; i < arr.length - 2 ; i++) {

            for(int j = 0 ; j < arr[0].length - 1 ; j++) {

                int val = arr[i][j] + arr[i+1][j] + arr[i+1][j+1]+ arr[i+2][j];

                max_Val = Math.max(max_Val , val);
            }
        }

        return max_Val;
    }

    public static int searchExcept4() {

        int max_Val = 0;

        for (int i = 0 ; i < arr.length - 2 ; i++) {

            for(int j = 1 ; j < arr[0].length  ; j++) {

                int val = arr[i][j] + arr[i+1][j] + arr[i+1][j-1]+ arr[i+2][j];

                max_Val = Math.max(max_Val , val);
            }
        }

        return max_Val;

    }
}

 

제귀로 그냥 상화좌우를 4칸 움직이도록 해서 배열에서 움직인 칸들의 합을 구해서 최댓값을 비교 및 갱신하도록 합니다.

예외로는 1가지 테트로미노인데 이를 상, 화 , 좌 , 우 반전 및 회전한 4가지 경우를 배열안에서 모두 검사하도록 합니다.