백준 테트로미노

KIMYEONGJUN·2026년 2월 20일
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500)
둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다.
i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다.
입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다.

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

내가 이 문제를 보고 생각해본 부분

입력 처리 및 데이터 저장
먼저 BufferedReader와 StringTokenizer를 통해 입력을 빠르게 받는다.
첫 줄에 종이의 세로 크기 N과 가로 크기 M을 받고, 두 번째 줄부터 N줄에 걸쳐 각 칸에 적힌 숫자를 2차원 배열 paper[N][M]에 저장한다.
이 배열은 이후 테트로미노 칸에 대응되는 값을 계산할 때 사용된다.
테트로미노 모양 정의
문제에 제시된 5가지 기본 테트로미노 모양을 회전과 대칭까지 모두 포함해 19가지 경우로 정리해둔다.
각 모양은 4개의 칸 위치를 기준점 (0,0)에서 상대좌표로 저장한다.
예를 들어, I 모양은 가로일 때 좌표 {(0,0),(0,1),(0,2),(0,3)}, 세로일 때 {(0,0),(1,0),(2,0),(3,0)} 처럼 저장된다.
모든 위치에서 모든 모양 적용
종이의 모든 칸을 기준점으로 삼아 테트로미노 모양들을 각각 적용해보며 반복한다.
내부 반복문에서 각 모양의 4칸씩 더해가면서, 만약 범위를 벗어나면 해당 모양과 위치 조합은 무효로 간주하여 더 이상 계산하지 않는다.
최댓값 갱신
올바른 위치에서 각 모양의 칸들이 종이 안에 모두 들어맞을 경우, 그 칸들의 숫자를 합산한다.
그리고 현재까지 기록된 최대 합 maxSum과 비교해 크면 갱신한다.
출력 및 종료
모든 위치와 모양 조합을 시도한 후, maxSum이 테트로미노가 놓인 칸 숫자들의 최대합이므로 이를 출력한다.
마지막에 리소스 누수를 막기 위해 br.close()로 스트림을 닫는다.

코드로 구현

package baekjoon.baekjoon_33;

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

// 백준 14500번 문제
public class Main1304 {
    static int N, M;
    static int[][] paper;
    // 테트로미노 모양들 (모든 회전과 반전 포함), 19가지 모양
    static int[][][] shapes = {
            {{0,0},{0,1},{0,2},{0,3}}, // I 가로
            {{0,0},{1,0},{2,0},{3,0}}, // I 세로
            {{0,0},{0,1},{1,0},{1,1}}, // O
            {{0,0},{1,0},{2,0},{2,1}}, // L
            {{0,1},{1,1},{2,1},{2,0}}, // L 반전
            {{0,0},{0,1},{1,1},{2,1}}, // L 회전 90
            {{0,0},{0,1},{1,0},{2,0}}, // L 회전 90 반전
            {{0,0},{0,1},{0,2},{1,0}}, // L 회전 180
            {{0,0},{0,1},{0,2},{1,2}}, // L 회전 180 반전
            {{0,2},{1,0},{1,1},{1,2}}, // L 회전 270
            {{0,0},{1,0},{1,1},{1,2}}, // L 회전 270 반전
            {{0,0},{1,0},{1,1},{2,1}}, // S
            {{0,1},{1,0},{1,1},{2,0}}, // S 반전
            {{0,1},{0,2},{1,0},{1,1}}, // S 세로 변형
            {{0,0},{0,1},{1,1},{1,2}}, // S 세로 반전
            {{0,0},{0,1},{0,2},{1,1}}, // T
            {{0,1},{1,0},{1,1},{1,2}}, // T 회전 90
            {{0,1},{1,0},{1,1},{2,1}}, // T 회전 180
            {{0,0},{1,0},{1,1},{2,0}}  // T 회전 270
    };

    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());
        paper = new int[N][M];

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

        int maxSum = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                for (int[][] shape : shapes) {
                    int sum = 0;
                    boolean valid = true;

                    for (int[] block : shape) {
                        int x = i + block[0];
                        int y = j + block[1];

                        if (x < 0 || y < 0 || x >= N || y >= M) {
                            valid = false;
                            break;
                        }
                        sum += paper[x][y];
                    }

                    if (valid && sum > maxSum) {
                        maxSum = sum;
                    }
                }
            }
        }

        System.out.println(maxSum);
        br.close();
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글