Skip to content
CatBus

Posts

All the articles I've posted.

BOJ21608GOLD 5

학생은 1번부터 N²번까지 번호가 매겨져 있고, (r, c)는 r행 c열을 의미한다. (r, c)의 인접한 칸은 (r-1, c), (r+1, c), (r, c-1), (r, c+1)이다.

학생이 좋아하는 학생 4명이 주어지고, 다음 순서로 자리를 배정한다.

  1. 비어있는 칸 중에서 좋아하는 학생이 인접한 칸에 가장 많은 칸으로 자리를 정한다.
  2. 1을 만족하는 칸이 여러 개이면, 인접한 칸 중에서 비어있는 칸이 가장 많은 칸으로 자리를 정한다.
  3. 2를 만족하는 칸도 여러 개인 경우에는 행의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정한다.

학생의 만족도는 자리 배치가 모두 끝난 후에 구할 수 있다. 학생의 만족도를 구하려면 그 학생과 인접한 칸에 앉은 좋아하는 학생의 수를 구해야 한다. 그 값이 0이면 0, 1이면 1, 2이면 10, 3이면 100, 4이면 1000이다.

구현 문제이다. 주어진 규칙대로 정확하게 구현하면 된다.

상어 초등학교

백준 21608번 '상어 초등학교' (골드 5) 문제 풀이. implementation 로 접근했다.

2025.05.10·4분·implementation
PROGRAMMERS301650SQL
SELECT e1.id
FROM ecoli_data AS e1
    JOIN ecoli_data AS e2 ON e1.parent_id = e2.id
    JOIN ecoli_data AS e3 ON e2.parent_id = e3.id
WHERE e3.parent_id IS NULL
ORDER BY e1.id ASC

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

  • 테이블 2회 JOIN 으로 두 테이블을 연결
  • WHERE 로 조건에 맞는 행만 남김
  • ORDER BY 로 정렬

특정 세대의 대장균 찾기

ecoli_data 를 세 번 조인해 부모의 부모까지 거슬러 올라가고, 그 위가 NULL 인 경우만 남겨 3세대를 찾는다.

2025.05.07·1분·sql
PROGRAMMERS301649SQL
WITH per AS (
    SELECT id, PERCENT_RANK() OVER (ORDER BY size_of_colony DESC) as per_rank
    FROM ECOLI_DATA
)
SELECT id,
CASE
    WHEN per_rank < 0.25 THEN 'CRITICAL'
    WHEN per_rank < 0.5 THEN 'HIGH'
    WHEN per_rank < 0.75 THEN 'MEDIUM'
    ELSE 'LOW'
END AS colony_name
FROM per
ORDER BY id;

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

  • ORDER BY 로 정렬 (내림차순 포함)
  • 서브쿼리를 사용
  • CASE WHEN 으로 조건에 따라 값을 분기

대장균의 크기에 따라 분류하기 2

PERCENT_RANK() 윈도 함수로 크기 백분위를 매기고, CASE 로 25%·50%·75% 구간을 잘라 등급 이름을 붙인다.

2025.05.07·1분·sql
BOJ18352SILVER 2

첫째 줄에 도시의 개수 N, 도로의 개수 M, 거리 정보 K, 출발 도시의 번호 X가 주어진다. (2 ≤ N ≤ 300,000, 1 ≤ M ≤ 1,000,000, 1 ≤ K ≤ 300,000, 1 ≤ X ≤ N)

둘째 줄부터 M개의 줄에 걸쳐서 두 개의 자연수 A, B가 공백을 기준으로 구분되어 주어진다. 이는 A번 도시에서 B번 도시로 이동하는 단방향 도로가 존재한다는 의미다. (1 ≤ A, B ≤ N)

출력

X로부터 출발하여 도달할 수 있는 도시 중에서, 최단 거리가 K인 모든 도시의 번호를 한 줄에 하나씩 오름차순으로 출력한다.

이 때 도달할 수 있는 도시 중에서, 최단 거리가 K인 도시가 하나도 존재하지 않으면 -1을 출력한다.

단방향 그래프에서 특정 노드로부터의 최단 거리를 구하는 문제이다. 모든 간선의 가중치가 1이므로 BFS 또는 다익스트라로 해결할 수 있다.

import heapq
from collections import defaultdict

INF = float("inf")

N, M, K, X = map(int, input().split())

graph = defaultdict(list)

for _ in range(M):
    a, b = map(int, input().split())
    graph[a].append(b)


def dijkstra(start):
    dist_list = [INF] * (N + 1)
    dist_list[start] = 0
    q = [(0, start)]

    while q:
        dist, cur_node = heapq.heappop(q)
        if dist_list[cur_node] < dist:
            continue

        for n_node in graph[cur_node]:
            if dist + 1 < dist_list[n_node]:
                dist_list[n_node] = dist + 1
                heapq.heappush(q, (dist + 1, n_node))

    return dist_list


inf_cnt = 0
for node, dist in enumerate(dijkstra(X)[1:], start=1):
    if dist == K:
        print(node)
    else:
        inf_cnt += 1

if inf_cnt == N:
    print(-1)

특정 거리의 도시 찾기

백준 18352번 '특정 거리의 도시 찾기' (실버 2) 문제 풀이. graph theory, graph traversal, bfs 로 접근했다.

2025.05.07·4분·graph theory
BOJ2110GOLD 4
N, C = map(int, input().split())
houses = sorted([int(input()) for _ in range(N)])

# 집 사이 최소 거리
start = 1
# 집 사이 최대 거리
end = houses[-1] - houses[0]
result = 0

# C개의 공유기를 모두 설치할 수 있는 mid를 찾기기
while start <= end:
    mid = (start + end) // 2
    count = 1
    cur_house = houses[0]

    for i in range(1, N):
        # 현재 집과의 거리가 mid보다 크거나 같을 때 -> 설치 가능
        if houses[i] - cur_house >= mid:
            count += 1
            cur_house = houses[i]

    # 가능한 경우 더 큰 mid를 탐색
    if count >= C:
        result = mid
        start = mid + 1
    else:
        end = mid - 1

print(result)

공유기 설치

백준 2110번 '공유기 설치' (골드 4) 문제 풀이. binary search, parametric search 로 접근했다.

2025.05.06·5분·binary search
PROGRAMMERS273712SQL
WITH null_item as (SELECT t1.item_id
    FROM item_tree as t1
        LEFT JOIN
        item_tree as t2
        ON t1.item_id = t2.parent_item_id
    WHERE t2.item_id IS NULL
)

SELECT ii.item_id, ii.item_name, ii.rarity
FROM null_item as ni
    JOIN
    item_info as ii
    ON ni.item_id = ii.item_id
ORDER BY ii.item_id DESC

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

  • 테이블 2회 LEFT JOIN 으로 두 테이블을 연결
  • WHERE 로 조건에 맞는 행만 남김
  • ORDER BY 로 정렬 (내림차순 포함)
  • 서브쿼리를 사용

업그레이드 할 수 없는 아이템 구하기

item_tree 를 자기 자신과 LEFT JOIN 해서 자식이 없는(NULL 인) 아이템만 남긴다 — 더 업그레이드할 수 없는 아이템이다.

2025.05.05·1분·sql
PROGRAMMERS151137SQL
SELECT car_type, COUNT(car_id) as cars
FROM car_rental_company_car
WHERE options REGEXP '통풍시트|열선시트|가죽시트'
GROUP BY car_type
ORDER BY car_type

-- WHERE car.options like '%통풍시트%'
--     OR car.options like '%열선시트%'
--     OR car.options like '%가죽시트%'

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

  • WHERE 로 조건에 맞는 행만 남김
  • GROUP BY 로 묶어서 집계
  • ORDER BY 로 정렬
  • 사용한 함수: COUNT()

자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기

LIKE 를 OR 로 세 번 잇는 대신 REGEXP 로 세 옵션을 한 번에 매칭하고 차종별로 COUNT 한다. 원래 쓰던 LIKE 버전도 주석으로 남겨 두었다.

2025.05.05·1분·sql
BOJ1817SILVER 5
MAX_W = 1000
N, M = map(int, input().split())

if N != 0:
    books = list(map(int, input().split()))
    cnt = 1
    remain_w = M
    for book in books:
        # 더 넣을 수 없으면 포장
        if remain_w < book:
            cnt += 1
            remain_w = M
        remain_w -= book

    print(cnt)
else:
    print(0)

짐 챙기는 숌

백준 1817번 '짐 챙기는 숌' (실버 5) 문제 풀이. implementation, greedy algorithm, simulation 로 접근했다.

2025.05.05·2분·implementation
BOJ14499GOLD 4

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다.

둘째 줄부터 N개의 줄에 지도에 쓰여 있는 수가 북쪽부터 남쪽으로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 주사위를 놓은 곳의 수는 항상 0이다. 지도의 각 칸에 쓰여 있는 수는 10 미만의 자연수 또는 0이다.

마지막 줄에는 이동하는 명령이 순서대로 주어진다. 동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어진다.

출력

이동할 때마다 주사위의 윗 면에 쓰여 있는 수를 출력한다. 만약 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시하고, 출력도 하지 않는다.

주사위의 상태를 관리하며 시뮬레이션하는 구현 문제이다.

주사위 굴리기

백준 14499번 '주사위 굴리기' (골드 4) 문제 풀이. implementation, simulation 로 접근했다.

2025.05.05·5분·implementation