Skip to content
CatBus

카테고리: boj

"boj" 로 분류된 글.

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
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
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
BOJ1325SILVER 1
  • 각 컴퓨터마다 BFS: O(N + M)
  • 전체 N개 컴퓨터: O(N × (N + M))
  • N ≤ 10,000, M ≤ 100,000
  • 최악의 경우: 10,000 × 110,000 = 1,100,000,000

시간 제한이 5초이고, 파이썬은 초당 약 1억 번 연산이 가능하므로 통과 가능하다.

시간이 빡빡할 경우 다음 최적화를 고려할 수 있다:

  1. 빠른 입출력: sys.stdin.readline() 사용

  2. DFS 대신 BFS: 재귀 오버헤드 감소

  3. 조기 종료: 이미 방문한 노드 재탐색 방지

  4. 역방향 그래프: A→B가 아닌 B→A로 저장

  5. 자기 자신 포함: 해킹한 컴퓨터 자신도 카운트에 포함

  6. 오름차순 출력: 여러 개일 경우 정렬 필요

  7. 빠른 입출력: N, M이 크므로 필수

이 문제는 “신뢰 관계”를 반대로 생각해야 한다:

  • “A가 B를 신뢰” ≠ A를 해킹하면 B도 해킹됨 (X)
  • “A가 B를 신뢰” = B를 해킹하면 A도 해킹됨 (O)

효율적인 해킹

백준 1325번 '효율적인 해킹' (실버 1) 문제 풀이. graph theory, graph traversal, bfs 로 접근했다.

2025.04.22·7분·graph theory
BOJ1043GOLD 4
def find(parent, x):
    if parent[x] != x:
        parent[x] = find(parent, parent[x])
    return parent[x]

def union(parent, a, b):
    a = find(parent, a)
    b = find(parent, b)
    if a < b:
        parent[b] = a
    else:
        parent[a] = b

N, M = map(int, input().split())
truth = list(map(int, input().split()))
truth_num = truth[0]
truth_people = set(truth[1:])

parent = list(range(N + 1))
parties = []

for _ in range(M):
    party = list(map(int, input().split()))
    party_people = party[1:]
    parties.append(party_people)
    
    # 같은 파티 사람들을 union
    for i in range(len(party_people) - 1):
        union(parent, party_people[i], party_people[i + 1])

# 진실을 아는 사람들과 같은 그룹인지 확인
result = 0
for party in parties:
    can_lie = True
    for person in party:
        for truth_person in truth_people:
            if find(parent, person) == find(parent, truth_person):
                can_lie = False
                break
        if not can_lie:
            break
    if can_lie:
        result += 1

print(result)

거짓말

백준 1043번 '거짓말' (골드 4) 문제 풀이. graph theory, data structures, graph traversal 로 접근했다.

2025.04.22·8분·graph theory
BOJ1652SILVER 5
import re

N = int(input())
room = [input() for _ in range(N)]

# 가로
row_cnt = sum(len(re.findall(r'\.{2,}', row)) for row in room)

# 세로
transposed = [''.join(row[i] for row in room) for i in range(N)]
col_cnt = sum(len(re.findall(r'\.{2,}', col)) for col in transposed)

print(row_cnt, col_cnt)

정규표현식 \.{2,}는 “연속된 2개 이상의 .”을 의미한다.

누울 자리를 찾아라

백준 1652번 '누울 자리를 찾아라' (실버 5) 문제 풀이. implementation, string 로 접근했다.

2025.04.18·7분·implementation
BOJ13549GOLD 5
N, K = map(int, input().split())
distance = [float('inf')] * 100001

def bfs_01(start):
    dq = deque([(0, start)])
    distance[start] = 0
    
    while dq:
        dist, c = dq.popleft()
        
        if distance[c] < dist:
            continue
            
        # 비용 0인 간선 (순간이동)
        n = c * 2
        if 0 <= n <= 100000 and dist < distance[n]:
            distance[n] = dist
            dq.appendleft((dist, n))  # 앞에 추가
        
        # 비용 1인 간선 (걷기)
        for n in (c + 1, c - 1):
            if 0 <= n <= 100000 and dist + 1 < distance[n]:
                distance[n] = dist + 1
                dq.append((dist + 1, n))  # 뒤에 추가

bfs_01(N)
print(distance[K])

숨바꼭질 3

백준 13549번 '숨바꼭질 3' (골드 5) 문제 풀이. graph theory, graph traversal, bfs 로 접근했다.

2025.04.17·7분·graph theory