백준 2539 - 모자이크

Computer Science/Problem Solving

문제 설명

입출력 및 제한사항

풀이

문제 요약은 다음과 같다. n × m 도화지에 잘못 칠해진 칸의 좌표가 주어진다. 한 변 길이가 같은 정사각형 색종이를 최대 k장 사용할 수 있고, 색종이는 도화지의 아래 변에 붙여서 사용한다. 모든 잘못 칠해진 칸을 가릴 수 있도록 할 때, 필요한 색종이의 최소 한 변 길이 s를 구하는 문제이다.

 

항상 도화지의 아래 변에 붙여서 사용하기 때문에 y 좌표는 생각하지 않아도 된다. 아래 붙여서 사용했을 때 x축에서 가장 멀리 떨어져있는 y좌표의 값만 넘긴다면 x 좌표만 생각하면 된다.

 

뭔가 이분 탐색하기엔 범위가 너무 좁아서 긴가민가했는데 다른 효율적인 풀이가 마땅히 생각나지 않아 이분 탐색으로 풀이했다. 탐색 조건은 종이의 크기이고 중앙값이 모든 좌표를 커버한다면 종이가 더 작아도 되므로 right = mid, 커버하지 못한다면 종이가 더 커야하므로 left = mid로 조건을 주었다.

내 코드

import sys
input = sys.stdin.readline
mis = lambda: map(int, input().split())
INF = float('inf')

n, m = mis()
paper_cnt = int(input())
miss_cnt = int(input())
coor = [[*mis()] for _ in range(miss_cnt)]

min_size = max(coor, key= lambda x: x[0])[0]
x_coor = sorted({i[1] for i in coor})

def check(s, coor):
    if s < min_size:
        return False
    
    used = 0
    i = 0
    n = len(coor)
    while i < n:
        used += 1
        cover_to = coor[i] + s - 1
        
        while i < n and coor[i] <= cover_to:
            i += 1
        
        if used > paper_cnt:
            return False

    return True

left = 0
right = 1000001
while left + 1 < right:
    mid = (left + right) // 2
    
    if check(mid, x_coor):
        right = mid
    else:
        left = mid
print(right)

이분탐색의 로직은 위에서 설명한 그대로이고, 커버할 수 있는지 판별하는 check 함수는 그리디하게 구성했다.

아직 덮지 않은 가장 왼쪽 열 x를 잡고, 색종이 1장을 [x, x+s-1] 범위로 깔고 이 구간에 포함되는 열들은 모두 건너뛴다. 이 과정을 반복해서 사용한 장수가 k를 초과하면 실패, 끝까지 덮으면 성공으로 판별한다.

 

사실 min_size부터 시작한다면 check 함수 내부에서 min_size 판별을 굳이 안해도 되지만 이분탐색 범위를 넉넉하게 잡는 습관이 들다보니,,, ㅎㅎ

 

시간 복잡도

이분탐색: O(logN)

check(): O(n) (중복이 제거되어서 실제론 n보다 작음)

따라서 총 시간 복잡도는 O(n logN)

고찰

만약 도화지의 아래에 붙여서 사용한다는 조건이 없다면 어떻게 풀이해야 할까? 이제는 1차원이 아니라 2차원에서 최적을 판단해야한다. 기존처럼 이분탐색으로 풀이가 가능할 것 같은데, check 함수를 올바르게 수정해야한다. 

 

아직 덮이지 않은 가장 왼쪽 아래의 점 p를 하나 잡고, p를 꼭짓점으로 덮는 정사각형의 위치만 재귀로 탐색하는 아이디어를 생각해볼 수 있을 것 같다. 완전탐색 비슷하게!

 

 

'Computer Science > Problem Solving' 카테고리의 다른 글

프로그래머스 - 멀리 뛰기  (0) 2025.11.03
프로그래머스 - 타겟 넘버  (0) 2025.10.30
백준 21278 - 호석이 두 마리 치킨  (0) 2025.09.18
백준 16946 - 벽 부수고 이동하기 4  (0) 2025.09.14
백준 1106 - 호텔  (0) 2025.09.09
'Computer Science/Problem Solving' 카테고리의 다른 글
  • 프로그래머스 - 멀리 뛰기
  • 프로그래머스 - 타겟 넘버
  • 백준 21278 - 호석이 두 마리 치킨
  • 백준 16946 - 벽 부수고 이동하기 4
hojoo
hojoo
그냥 개발이 즐거운 사람
  • hojoo
    dev_record
    hojoo
  • 전체
    오늘
    어제
    • 분류 전체보기 (82)
      • Study (0)
        • 모든 개발자를 위한 HTTP 웹 기본 지식 (0)
        • Real MySQL 8.0 (0)
        • 친절한 SQL 튜닝 (0)
        • 도메인 주도 개발 시작하기 (0)
        • 대규모 시스템 설계 기초 (0)
      • Computer Science (66)
        • Problem Solving (30)
        • Data Structure (4)
        • Spring Boot (13)
        • DB (1)
        • Java (4)
        • OS (3)
        • Server (2)
        • Tech (0)
      • Security (16)
        • Reversing (15)
        • Assembly (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    n+1
    19622
    DP
    x64dbg
    Reversing
    Header
    bean
    PE header
    16946
    13265
    2539
    자료구조
    백준
    레나 튜토리얼
    HTTP
    dreamhack.io
    프로그래머스
    리버싱
    서버 증설 횟수
    servlet
    Lena tutorial
    Spring boot
    n^2 배열 자르기
    리버싱 핵심원리
    12033
    15973
    9421
    DB
    21278
    소수상근수
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
hojoo
백준 2539 - 모자이크
상단으로

티스토리툴바