Posts
All the articles I've posted.
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 로 접근했다.
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 로 접근했다.
-- 코드를 입력하세요
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) 로 묶고, 주소가 '서울' 로 시작하는 곳만 남긴 뒤 평점·즐겨찾기 순으로 정렬한다.
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 로 모은 뒤, 아이템 정보와 조인한다.
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 로 만든 뒤 어종과 길이를 둘 다 조건에 걸어 조인해, 종마다 가장 큰 개체만 남긴다.
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 로 접근했다.
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 로 접근했다.
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 로 접근했다.
첫 번째 줄에는 회전 초밥 벨트에 놓인 접시의 수 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 로 접근했다.