[백준 10026] 적록색약 (Python)

문제 링크 #

문제 해설 #

Idea #

  • 모든 방문하지 않은 칸에 대해 BFS 탐색하면서 같은 구역을 방문
  • 적록색약의 경우 R과 G를 같은 구역으로 판단하고 탐색
  • 각각의 경우에 대한 BFS 호출 횟수를 서로 다른 구역의 수로 판단하여 출력

Time Complexity #

  • BFS: O(N^2) = 10,000

Data Size #

  • N: 1 <= int <= 100

해설 코드 #

python
from collections import deque
import sys
input = sys.stdin.readline

N = int(input())
grid = [list(input().strip()) for _ in range(N)]
visited = [[[False] * N for _ in range(N)] for _ in range(2)]
answer = [0, 0]

def bfs(start, visited, st):
    queue = deque([start])
    dy = [0,1,0,-1]
    dx = [-1,0,1,0]

    while queue:
        y,x = queue.popleft()
        for i in range(4):
            ny, nx = y+dy[i], x+dx[i]
            if 0<=ny<N and 0<=nx<N and not visited[ny][nx]:
                if st[grid[y][x]] == st[grid[ny][nx]]:
                    queue.append((ny,nx))
                    visited[ny][nx] = True
    return 1

for i in range(N):
    for j in range(N):
        if not visited[0][i][j]:
            answer[0] += bfs((i,j), visited[0], {'R':0,'G':1,'B':2})
        if not visited[1][i][j]:
            answer[1] += bfs((i,j), visited[1], {'R':0,'G':0,'B':2})

print(answer[0], answer[1])

[백준 21758] 꿀 따기 (Python)

문제 링크 #

문제 해설 #

Idea #

  • 벌이 같은 방향을 향하는 경우 상자까지의 총합에서 두 벌의 시작 위치에 있는 값을 제외
  • 벌이 다른 방향을 향하는 경우 상자까지의 총합에 절댓값을 취해서 더함

Data Size #

  • N: 3 <= int <= 100,000
  • arr[i]: 1 <= int <= 10,000

해설 코드 #

python
N = int(input())
arr = list(map(int, input().split()))
forward, backward = [arr[0]]+[0]*(N-1), [0]*(N-1)+[arr[-1]]
for i in range(1,N):
    forward[i] = forward[i-1] + arr[i]
    backward[N-i-1] = backward[N-i] + arr[N-i-1]
answer = 0

for i in range(1,N-1):
    answer = max(answer, forward[N-1]*2-forward[0]-forward[i-1]-arr[i]*2)
    answer = max(answer, backward[0]*2-backward[N-1]-backward[N-i]-arr[N-i-1]*2)
    answer = max(answer, forward[i]-arr[0]+backward[i]-arr[-1])

print(answer)

[백준 5547] 일루미네이션 (Python)

문제 링크 #

문제 해설 #

Idea #

  • 전체 좌표 평면의 외곽에 1만큼의 여백을 추가하고 x,y 좌표가 0부터 시작한다고 판단
  • y가 홀수 일 때, 인접한 좌표는 상하좌우와 함께 우상단,우하단을 포함
  • y가 짝수 일 때, 인접한 좌표는 상하좌우와 함께 좌상단, 좌하단을 포함
  • 건물이 없는 좌표를 BFS 탐색하면서 건물과 만나는 지점을 카운트

Time Complexity #

  • BFS: O(N^2) = 10,000

Data Size #

  • W, H: 1 <= int <= 100

해설 코드 #

python
from collections import deque
import sys
input = sys.stdin.readline

W, H = map(lambda x: int(x)+2, input().split())
maps = [[0] * W for _ in range(H)]
for i in range(1,H-1):
    maps[i] = [0]+list(map(int, input().split()))+[0]
visited = [[False] * W for _ in range(H)]

def bfs(start):
    queue = deque([start])
    dy = [0,1,0,-1,1,-1]
    cnt = 0

    while queue:
        y,x = queue.popleft()
        dx = [-1,0,1,0,-1,-1] if y%2==0 else [-1,0,1,0,1,1]
        for i in range(6):
            ny, nx = y+dy[i], x+dx[i]
            if 0<=ny<H and 0<=nx<W:
                if maps[ny][nx] == 0 and not visited[ny][nx]:
                    queue.append((ny,nx))
                    visited[ny][nx] = True
                elif maps[ny][nx] == 1:
                    cnt += 1
    return cnt

visited[0][0] = True
print(bfs((0,0)))

[백준 1308] D-Day (Python)

문제 링크 #

문제 해설 #

Idea #

  • 각각의 날짜에 대한 문자열을 date 타입으로 변환하고, today 기준 1000년 후 날짜와 dday를 비교
  • 조건이 맞을 경우 ‘gg’를 출력하고, 아니면 두 날짜의 차이를 출력

Data Size #

  • y,m,d: 1,1,1 <= int*3 <= 9999,12,31

해설 코드 #

python
from datetime import date
strptime = lambda: date(**{k:int(v) for k,v in zip(['year','month','day'],input().split())})
today, dday = strptime(), strptime()
if dday >= today.replace(today.year+1000):
    print('gg')
else:
    print('D-'+str((dday-today).days))

[백준 7569] 토마토 (Python)

문제 링크 #

문제 해설 #

Idea #

  • BFS
  • 7569번 토마토 문제에서 하나의 차원이 추가된 버전입니다.
  • 차원이 늘어난만큼 N의 최대 길이가 감소했기 때문에 여전히 BFS로 해결할 수 있습니다.
  • 익은 토마토의 기준에서 전체 상자를 BFS로 완전탐색하면서 안익은 토마토까지의 최소 거리를 기록합니다.
  • 최소 거리의 최댓값이 곧 토마토들이 모두 익는 최소 일수이며,
    모든 토마토가 다 익었을 경우에 최소 일수를 출력하고, 그렇지 않은 경우엔 -1을 출력합니다.

Time Complexity #

  • O(N^3) = 1,000,000

Data Size #

  • M,N: 2 <= int <= 100
  • H: 1 <= int <= 100
  • t in [1,0,-1]

해설 코드 #

python
from collections import deque
import sys
input = sys.stdin.readline

M, N, H = map(int, input().split())
box = [[list(map(int, input().split())) for _ in range(N)] for _ in range(H)]
queue = deque([(h,r,c) for h in range(H) for r in range(N) for c in range(M) if box[h][r][c]==1])
days = 0

dz = [0,0,0,0,1,-1]
dy = [0,1,0,-1,0,0]
dx = [-1,0,1,0,0,0]

while queue:
    z,y,x = queue.popleft()
    days = max(days, box[z][y][x])
    for i in range(6):
        nz,ny,nx = z+dz[i],y+dy[i],x+dx[i]
        if 0<=nz<H and 0<=ny<N and 0<=nx<M and box[nz][ny][nx]==0:
            box[nz][ny][nx] = box[z][y][x] + 1
            queue.append((nz,ny,nx))

if 0 in {cell for layer in box for row in layer for cell in row}:
    print(-1)
else:
    print(days-1)

[백준 7576] 토마토 (Python)

문제 링크 #

문제 해설 #

Idea #

  • BFS를 활용한 시뮬레이션을 통해 모든 토마토가 익을 떄까지 걸리는 최소 기간을 계산
  • 초기엔 안익은 토마토의 기준에서 매번 익은 토마토까지의 최단거리를 탐색하여,
    O(N^4)의 시간 복잡도로 시간 초과가 발생
  • 이후 익은 토마토의 기준에서 시뮬레이션을 단 한번만 수행하여 각각의 칸에 도달하는데 걸리는 거리값을 갱신
  • 모두 익지 못하는 상황에 대해 1안에선 에러를 발생시켜 처리했고, 2안에선 종료 코드를 실행해 처리

Time Complexity #

  • O(N^2) = 1,000,000

Data Size #

  • M,N: 2 <= int <= 1,000
  • t in [1,0,-1]

해설 코드 #

python
from collections import deque
import sys
input = sys.stdin.readline

M, N = map(int, input().split())
box = [list(map(int, input().split())) for _ in range(N)]
days = 0

# ============== 1안 (시간초과) =============

def bfs(graph, start, n, m, vistied):
    queue = deque([start])
    dist = 0

    dy = [0,1,0,-1]
    dx = [-1,0,1,0]

    while queue:
        for _ in range(len(queue)):
            y,x = queue.popleft()
            if graph[y][x] == 1:
                return dist
            for i in range(4):
                ny,nx = y+dy[i],x+dx[i]
                if 0<=ny<n and 0<=nx<m and not vistied[ny][nx] and graph[ny][nx]!=-1:
                    queue.append((ny,nx))
                    vistied[ny][nx] = True
        dist += 1
    raise Exception()

try:
    for i in range(N):
        for j in range(M):
            if box[i][j] == 0:
                vistied = [[False] * M for _ in range(N)]
                vistied[i][j] = True
                days = max(days, bfs(box, (i,j), N, M, vistied))
    print(days)
except Exception:
    print(-1)

# =============== 2안 (통과) ===============

queue = deque()
for i in range(N):
    for j in range(M):
        if box[i][j] == 1:
            queue.append((i,j))

def bfs(graph, queue, n, m):
    dy = [0,1,0,-1]
    dx = [-1,0,1,0]

    while queue:
        y,x = queue.popleft()
        for i in range(4):
            ny,nx = y+dy[i],x+dx[i]
            if 0<=ny<n and 0<=nx<m and graph[ny][nx]==0:
                graph[ny][nx] = graph[y][x] + 1
                queue.append((ny,nx))

bfs(box, queue, N, M)
for i in range(N):
    for j in range(M):
        if box[i][j] == 0:
            print(-1)
            exit(0)
        days = max(days, box[i][j])
print(days-1)

[백준 18870] 좌표 압축 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Sort
  • 집합을 통해 압축한 unique한 좌표 목록을 정렬시키고,
    정렬된 리스트 내에서 좌표와 인덱스를 딕셔너리로 맵핑

Time Complexity #

  • O(N Log N) = 13,000,000

Data Size #

  • N: 1 <= int <= 1,000,000
  • X: -10^9 <= int <= 10^9

해설 코드 #

python
N = int(input())
X = list(map(int, input().split()))
xtoi = {x:i for i,x in enumerate(sorted(set(X)))}
print(' '.join(map(lambda x: str(xtoi[x]), X)))

[백준 1931] 회의실 배정 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Sliding Window
  • 슬라이딩 윈도우의 전형적인 문제로, 끝 시간을 기준으로 시간을 정렬해서 겹치지 않는 수를 계산

Time Complexity #

  • O(N) = 100,000

Data Size #

  • N: 1 <= int <= 100,000
  • t1,t2: 0 <= int <= 2^31-1

해설 코드 #

python
import sys
input = sys.stdin.readline

N = int(input())
times = sorted([tuple(map(int, input().split())) for _ in range(N)], key=lambda x: [x[1],x[0]])
count, end_time = 0, 0

for t1,t2 in times:
    if t1 >= end_time:
        count += 1
        end_time = t2

print(count)

[백준 15686] 치킨 배달 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Combinations
  • 최대 집의 개수가 100, 최대 치킨집의 개수가 13으로 매우 적은 경우의 수를 가지고 있기 때문에,
    모든 조합에 대한 완전탐색을 통해 최소 거리를 계산
  • 초기에는 집에 대한 치킨 거리가 작은 치킨집을 우선적으로 선발해서,
    폐업하지 않은 치킨집에 대한 치킨 거리의 최소 합을 계산했지만 틀림
  • 이후 combinations 모듈을 활용한 완전탐색을 통해 통과

Time Complexity #

  • O(N * nCr) ~ 100,000

Data Size #

  • N: 2 <= int <= 50
  • M: 1 <= int <= 13
  • cell in (0, 1, 2)
  • count(house): 1 <= int < 2N
  • count(chicken): M <= int <= 13

해설 코드 #

python
from itertools import combinations
import sys
input = sys.stdin.readline

N, M = map(int, input().split())
city = {'0':list(),'1':list(),'2':list()}
for r in range(N):
    for c,i in enumerate(input().split()):
        city[i].append((r,c))
houses, chickens = city['1'], city['2']
diff = lambda c1,c2: abs(c1[0]-c2[0])+abs(c1[1]-c2[1])

# =============== 1안 (틀림) ===============

house_cost = {chicken:0 for chicken in chickens}
chicken_cost = {house:house_cost.copy() for house in houses}

for house in houses:
    for chicken in chickens:
        cost = diff(house,chicken)
        chicken_cost[house][chicken] = cost
        house_cost[chicken] += cost

city_cost = 0
open = [chicken for chicken,cost in sorted(house_cost.items(), key=lambda x: x[1])[:M]]
for house, costs in chicken_cost.items():
    city_cost += min([cost for chicken,cost in costs.items() if chicken in open])

# =============== 2안 (통과) ===============

city_cost = sys.maxsize
for comb in combinations(chickens, M):
    cost = 0
    for house in houses:
        cost += min([diff(house,chicken) for chicken in comb])
    city_cost = min(city_cost,cost)

print(city_cost)

[백준 1927] 최소 힙 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Heapq
  • 파이썬 heapq 모듈 자체가 최소힙이기 때문에 해당하는 기능을 활용하여 구현

Time Complexity #

  • O(Log N) = 16

Data Size #

  • N: 1 <= int <= 100,000
  • x: 0 <= int < 2^31

해설 코드 #

python
import heapq
import sys
input = sys.stdin.readline

N = int(input())
arr = list()

for _ in range(N):
    x = int(input())
    if x > 0:
        heapq.heappush(arr, x)
    else:
        if arr:
            print(heapq.heappop(arr))
        else:
            print(0)