[백준] 테트로미노

개발자 P군·2026년 2월 2일

백준

목록 보기
55/57
post-thumbnail

🔗 문제 보기 - [백준] 테트로미노

📖 문제

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.

정사각형은 서로 겹치면 안 된다.
도형은 모두 연결되어 있어야 한다.
정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.

아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.

테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.

테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.

✍ 입력

첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500)

둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다. i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다. 입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다.

📄 출력

첫째 줄에 테트로미노가 놓인 칸에 쓰인 수들의 합의 최댓값을 출력한다.

✅ 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    static int[] moveX = {-1, 1, 0, 0};
    static int[] moveY = {0, 0, -1, 1};
    static int N, M;
    static int[][] arr;
    static boolean[][] visited;
    static int maxVal = 0;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());       // 세로
        M = Integer.parseInt(st.nextToken());       // 가로
        arr = new int[N][M];
        visited = new boolean[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());
            }
        }

        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                dfs(i, j, 1, arr[i][j]);
                checkOther(i,j);
            }
        }

        System.out.println(maxVal);
    }

    // DFS로 depth 4까지 이동해서 큰값 구하기
    public static void dfs(int x, int y, int depth, int sum) {
        if(depth == 4) {
            maxVal = Math.max(maxVal, sum);
            return;
        }

        visited[x][y] = true;

        for(int i = 0; i < 4; i++) {
            int dx = x + moveX[i];
            int dy = y + moveY[i];

            if(0 <= dx && dx < N && 0 <= dy && dy < M && !visited[dx][dy]) {
                dfs(dx, dy, depth + 1, sum + arr[dx][dy]);
            }
        }

        visited[x][y] = false;
    }

    // 'ㅓ','ㅏ','ㅗ','ㅜ' 모양 탐색
    public static void checkOther(int x, int y) {
        int sum = arr[x][y];
        int min = Integer.MAX_VALUE;
        int wings = 0;

        for(int i = 0; i < 4; i++) {
            int dx = x + moveX[i];
            int dy = y + moveY[i];

            if(0 <= dx && dx < N && 0 <= dy && dy < M) {
                wings++;
                sum += arr[dx][dy];
                min = Math.min(min, arr[dx][dy]);
            }
        }

        // 4방향 모두 더했을 때()는 가장 작은 값을 sum에서 빼주면 됨
        if(wings == 4) {
            sum -= min;
        }


        maxVal = Math.max(maxVal, sum);
    }
}
profile
문제를 발견하고 해결하는 과정을 통해 얻은 새로운 지식을 공유하고자 합니다.

0개의 댓글