CS/Algorism

[백준] 18808. 스티커

olsohee 2023. 12. 8. 11:03

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

 

18808번: 스티커 붙이기

혜윤이는 최근에 다양한 대회를 참여하면서 노트북에 붙일 수 있는 스티커들을 많이 받았다. 스티커는 아래와 같이 사각 모눈종이 위에 인쇄되어 있으며, 스티커의 각 칸은 상하좌우로 모두 연

www.acmicpc.net

어려운 문제는 아니고 그냥 구현 문제이다. 그런데 스티커 회전이라든지, map에 붙일 수 있는지 없는지 이차원 배열의 범위를 탐색한다든지 짜잘하게 신경써야 할 것이 많다. 그리고 그만큼 실수하기 쉬운 문제이다. 다행히 몇 번 디버깅하면서 맞출 수 있었는데, 그래도 다음에 다시 풀면서 꼼꼼히 생각하자는 의미로 기록한다.

import java.io.BufferedReader;
import java.io.IOException;

import java.io.InputStreamReader;
import java.util.*;

public class Main {

    static int n; // 세로
    static int m; // 가로
    static int k; // 스티커 개수
    static int[][] map;
    static int answer = 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());
        k = Integer.parseInt(st.nextToken());
        map = new int[n][m];

        for (int i = 0; i < k; i++) {
            // 스티커 입력받기
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            int[][] sticker = new int[r][c];
            for (int j = 0; j < r; j++) {
                st = new StringTokenizer(br.readLine());
                for (int k = 0; k < c; k++) {
                    sticker[j][k] = Integer.parseInt(st.nextToken());
                }
            }

            // 스티커 붙이기
            putSticker(sticker);
        }

        // 스티커가 붙은 칸 수 계산
        getStickerArea();
        System.out.println(answer);
    }

    private static void putSticker(int[][] sticker) {

        for (int i = 0; i < 4; i++) {
            // 지금 방향에서 붙일 수 있는지 확인
            int stickerX = sticker[0].length; // 스티커의 가로 길이
            int stickerY = sticker.length; // 스티커의 세로 길이

            for (int j = 0; j <= (n - stickerY); j++) {
                for (int k = 0; k <= (m - stickerX); k++) {
                    // map 범위를 벗어나지 않는지 확인
                    if (j + stickerY > n || k + stickerX > m) {
                        continue;
                    }
                    // 붙이기(붙였으면 끝내기)
                    if (canPut(sticker, j, k)) {
                        return;
                    }
                }
            }
            // 90도로 스티커 회전
            sticker = rotation(sticker);
        }
    }

    private static boolean canPut(int[][] sticker, int startY, int startX) {
        int stickerX = sticker[0].length; // 스티커의 가로 길이
        int stickerY = sticker.length; // 스티커의 세로 길이

        // 붙일 수 있는지 확인 (스티커가 1인데 map도 1이면 못붙임)
        for (int i = 0; i < stickerY; i++) {
            for (int j = 0; j < stickerX; j++) {
                if (sticker[i][j] == 1 && map[i + startY][j + startX] == 1) {
                    return false;
                }
            }
        }

        // 붙일 수 있으면 스티커 붙이기
        for (int i = 0; i < stickerY; i++) {
            for (int j = 0; j < stickerX; j++) {
                if (sticker[i][j] == 1) {
                    map[i + startY][j + startX] = 1;
                }
            }
        }
        return true;
    }

    private static int[][] rotation(int[][] sticker) {
        int newX = sticker.length;
        int newY = sticker[0].length;
        int[][] newSticker = new int[newY][newX];

        for (int i = 0; i < newX; i++) {
            for (int j = 0; j < newY; j++) {
                newSticker[j][newX - i - 1] = sticker[i][j];
            }
        }
        return newSticker;
    }

    private static void getStickerArea() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (map[i][j] == 1) {
                    answer++;
                }
            }
        }
    }
}

'CS > Algorism' 카테고리의 다른 글

[백준] 1926. 그림  (1) 2023.12.26
[백준] 10816. 숫자 카드 2  (0) 2023.12.11
[백준] 1744. 수 묶기  (1) 2023.12.06
[백준] 11501. 주식  (2) 2023.12.06
[백준] 2457. 공주님의 정원  (2) 2023.12.05