Skip to content
CatBus

Posts

All the articles I've posted.

BOJ1966SILVER 3
import heapq

def nag_int(s):
    """음수 정수를 반환"""
    return -int(s)

TC = int(input())
for t in range(TC):
    N, M = map(int, input().split())
    importance_list = list(map(nag_int, input().split()))
    q = deque([(i, im) for i, im in enumerate(importance_list)])
    heapq.heapify(importance_list)

    cnt = 1
    cur_min = heapq.heappop(importance_list)

    while q:
        i, im = q.popleft()
        if i == M and cur_min == im:
            # M 번째 출력되면 끝
            break
        elif cur_min == im:
            # 출력 가능하면 다음으로
            cur_min = heapq.heappop(importance_list)
            cnt += 1
        else:
            # 출력 안되면 대기열 맨 뒤로
            q.append((i, im))
    print(cnt)

프린터 큐

백준 1966번 '프린터 큐' (실버 3) 문제 풀이. implementation, data structures, simulation 로 접근했다.

2025.06.26·3분·implementation
BOJ20055GOLD 5
N, K = map(int, input().split())
durability = deque(map(int, input().split()))
belt = deque([False] * (N * 2)) # belt 위에 로봇이 있는지 여부

PUT_IDX = 0
OUT_IDX = N - 1
round_num = 1

while True:
    # 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
    durability.rotate()
    belt.rotate()

    # 언제든지 로봇이 내리는 위치에 도달하면 그 즉시 내린다.
    belt[OUT_IDX] = False


    # 가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
    for i in range(N - 2, -1, -1):
        # 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.
        if not belt[i]:
            continue
        n_i = i + 1
        if not belt[n_i] and durability[n_i] >= 1:
            durability[n_i] -= 1
            belt[i] = False
            belt[n_i] = True
    
    # 언제든지 로봇이 내리는 위치에 도달하면 그 즉시 내린다.
    belt[OUT_IDX] = False

    # 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
    if durability[PUT_IDX]:
        durability[PUT_IDX] -= 1
        belt[PUT_IDX] = True
        
    # 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다. 그렇지 않다면 1번으로 돌아간다.
    if durability.count(0) >= K:
        break
    round_num += 1

print(round_num)

컨베이어 벨트 위의 로봇

백준 20055번 '컨베이어 벨트 위의 로봇' (골드 5) 문제 풀이. implementation, simulation 로 접근했다.

2025.06.26·3분·implementation
PROGRAMMERS131118SQL
-- 코드를 입력하세요
WITH rm AS (SELECT ri.rest_id,
            ri.rest_name,
            ri.food_type,
            ri.favorites,
            ri.address,
            ROUND(AVG(review_score), 2) AS score
    FROM rest_info AS ri
        JOIN
        rest_review AS rr
        ON ri.rest_id = rr.rest_id
    WHERE ri.address LIKE "서울%"
    GROUP BY ri.rest_id, RI.REST_NAME, RI.FOOD_TYPE, RI.FAVORITES, RI.ADDRESS)

SELECT *
FROM rm
ORDER BY score DESC, favorites DESC;

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

서울에 위치한 식당 목록 출력하기

CTE 안에서 식당과 리뷰를 조인해 평점을 ROUND(AVG(), 2) 로 묶고, 주소가 '서울' 로 시작하는 곳만 남긴 뒤 평점·즐겨찾기 순으로 정렬한다.

2025.06.26·1분·sql
PROGRAMMERS273711SQL
WITH rare_item AS (
    SELECT it.item_id
    FROM item_info AS ii
        JOIN
        item_tree AS it
        ON ii.item_id = it.parent_item_id
    WHERE rarity = "RARE"
)

# SELECT *
# FROM rare_item

SELECT ii.item_id, ii.item_name, ii.rarity
FROM rare_item AS ri
    JOIN
    item_info AS ii
    ON ri.item_id = ii.item_id
ORDER BY ii.item_id DESC

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

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

업그레이드 된 아이템 구하기

item_tree 에서 부모로 등장하는 아이템 중 rarity 가 RARE 인 것을 CTE 로 모은 뒤, 아이템 정보와 조인한다.

2025.06.26·1분·sql
PROGRAMMERS293261SQL
WITH max_fish AS (
    SELECT fish_type, MAX(length) AS max_length
    FROM fish_info
    GROUP BY fish_type
)

SELECT fi.id, fni.fish_name, fi.length
FROM fish_info fi
JOIN 
    max_fish mf
    ON fi.fish_type = mf.fish_type AND fi.length = mf.max_length
JOIN 
    fish_name_info fni
    ON fi.fish_type = fni.fish_type
ORDER BY 
    fi.id;

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

  • 테이블 2회 JOIN 으로 두 테이블을 연결
  • GROUP BY 로 묶어서 집계
  • ORDER BY 로 정렬
  • 서브쿼리를 사용
  • 사용한 함수: MAX()

물고기 종류 별 대어 찾기

어종별 MAX(length) 를 CTE 로 만든 뒤 어종과 길이를 둘 다 조건에 걸어 조인해, 종마다 가장 큰 개체만 남긴다.

2025.06.12·1분·sql
BOJ1389SILVER 1
from collections import defaultdict, deque

INF = float('inf')

def floyd(n, dist_list):
    for k in range(n):
        for i in range(n):
            for j in range(n):
                dist_list[i][j] = min(dist_list[i][j], dist_list[i][k] + dist_list[k][j])

    min_sum = INF
    result = 0
    for i, sum_dist in enumerate(map(sum, dist_list), start=1):
        if min_sum > sum_dist:
            min_sum = sum_dist
            result = i

    return result

def main():
    N, M = map(int, input().split())

    dist_list = [[INF] * N for _ in range(N)]
    for i in range(0, N):
        dist_list[i][i] = 0

    for _ in range(M):
        a, b = map(int, input().split())
        a -= 1
        b -= 1
        dist_list[a][b] = 1
        dist_list[b][a] = 1
    
    print(floyd(N, dist_list))


if __name__ == "__main__":
    main()

케빈 베이컨의 6단계 법칙

백준 1389번 '케빈 베이컨의 6단계 법칙' (실버 1) 문제 풀이. graph theory, graph traversal, bfs 로 접근했다.

2025.06.12·3분·graph theory
BOJ17281GOLD 4
from itertools import permutations

N = int(input())
hit_result = [list(map(int, input().split())) for _ in range(N)]

max_score = 0
# permutations는 애초에 중복 없음 → set() 필요 없음
for perm in permutations([i for i in range(1, 9)]):  # 1번 선수 제외 순열
    order = list(perm[:3]) + [0] + list(perm[3:])  # 0번(1번 선수) 4번 타자 고정

    score = 0
    idx = 0  # 타석 순서 인덱스
    for inning in hit_result:
        out = 0
        base1, base2, base3 = 0, 0, 0  # 각 루의 주자 (0/1)
        while out < 3:
            result = inning[order[idx]]
            if result == 0:
                out += 1
            elif result == 1:
                score += base3
                base1, base2, base3 = 1, base1, base2
            elif result == 2:
                score += base3 + base2
                base1, base2, base3 = 0, 1, base1
            elif result == 3:
                score += base3 + base2 + base1
                base1, base2, base3 = 0, 0, 1
            elif result == 4:
                score += base3 + base2 + base1 + 1
                base1, base2, base3 = 0, 0, 0
            idx = (idx + 1) % 9

    max_score = max(max_score, score)

print(max_score)

백준 17281번 '⚾' (골드 4) 문제 풀이. implementation, bruteforcing 로 접근했다.

2025.06.11·3분·implementation
BOJ11404GOLD 4
INF = float("inf")


def floyd(n, dist_list):
    """플로이드 워셜"""

    for k in range(1, n + 1):
        for i in range(1, n + 1):
            for j in range(1, n + 1):
                dist_list[i][j] = min(
                    dist_list[i][j], dist_list[i][k] + dist_list[k][j]
                )

    return dist_list


def print_result(dist_list):
    """결과 출력"""
    for dist in dist_list[1:]:
        for d in dist[1:]:
            print(d if d != INF else 0, end=" ")
        print()


def main():
    n = int(input())
    m = int(input())

    dist_list = [[INF] * (n + 1) for _ in range(n + 1)]

    for _ in range(m):
        a, b, c = map(int, input().split())
        dist_list[a][b] = min(dist_list[a][b], c)

    for i in range(1, n + 1):
        dist_list[i][i] = 0

    dist_list = floyd(n, dist_list)
    print_result(dist_list)


if __name__ == "__main__":
    main()

플로이드

백준 11404번 '플로이드' (골드 4) 문제 풀이. graph theory, shortest path, floyd warshall 로 접근했다.

2025.06.11·3분·graph theory
BOJ2531SILVER 1

첫 번째 줄에는 회전 초밥 벨트에 놓인 접시의 수 N, 초밥의 가짓수 d, 연속해서 먹는 접시의 수 k, 쿠폰 번호 c가 주어진다. 단, 2 ≤ N ≤ 30,000, 2 ≤ d ≤ 3,000, 2 ≤ k ≤ 3,000 (k ≤ N), 1 ≤ c ≤ d이다.

출력

주어진 회전 초밥 벨트에서 먹을 수 있는 초밥의 최대 가짓수를 출력하시오.

슬라이딩 윈도우 기법을 사용하는 문제이다.

from collections import defaultdict

N, d, k, c = map(int, input().split())
sushi_list = [int(input()) for _ in range(N)]

counter = defaultdict(int)
kind = 0

for i in range(k):
    if counter[sushi_list[i]] == 0:
        kind += 1
    counter[sushi_list[i]] += 1

# 쿠폰
max_kind = kind + (1 if counter[c] == 0 else 0)

for i in range(1, N):
    remove = sushi_list[i - 1]
    counter[remove] -= 1
    if counter[remove] == 0:  # 더 이상 없으면 종류 수 감소
        kind -= 1

    cur = sushi_list[(i + k - 1) % N]
    if counter[cur] == 0:
        kind += 1
    counter[cur] += 1

    # 쿠폰
    total = kind + (1 if counter[c] == 0 else 0)
    max_kind = max(max_kind, total)  # 최대 종류 수 갱신

print(max_kind)

회전 초밥

백준 2531번 '회전 초밥' (실버 1) 문제 풀이. bruteforcing, two pointer, sliding window 로 접근했다.

2025.05.14·3분·bruteforcing