한국정보올림피아드 문제풀이

안녕하세요.

올해도 KOI 대회를 준비하는 학생들이 있어 문제풀이를 시간날 때 마다 포스팅하려 합니다. 

풀이 결과가 100점이 아닌 경우도 있습니다.

여러분도 도전해보세요~😉 

 

KOI 2024 2차대회 

보물찾기

문제 백준링크

풀이

반복문으로 풀면 시간초과.

왼쪽, 오른쪽, 현재위치를 이용하면 규칙성이 보임.

t = int(input())

for _ in range(t):
    l, r, s = map(int, input().split(' '))
    lr = set([l, r])

    if s in lr:
        print(1)
    else:        
        a = s-l
        b = r-s
        if a<b:
            print(a*2+1)
        elif a>b:
            print(b*2)          
        else:
            print(a*2)
            

 

가로등

문제 백준링크 

풀이

위치와 어두운 정도를 묶어서 딕셔너리로 정리.

이후 어두운 정도를 기준으로 정렬 후 출력.

from collections import deque
import sys

L, N, K = map(int, sys.stdin.readline().rstrip().split(' '))
lst = list(map(int, sys.stdin.readline().rstrip().split(' ')))

visit = set()
q = deque()
d = dict() 
for i in range(N):
    visit.add(lst[i])
    d[lst[i]] = 0
    q.append(lst[i])

cnt = 0
while q:
    i = q.popleft()
    cnt += 1
    if i - 1 >= 0 and i - 1 not in visit:
        d[i - 1] = d[i] + 1
        visit.add(i - 1)
        q.append(i - 1)
    if i + 1 <= L and i + 1 not in visit:
        d[i + 1] = d[i] + 1
        visit.add(i + 1)
        q.append(i + 1)
    if cnt >= K:
        break

# value 기준 정렬
#print(d)
sd = sorted(d.items(), key=lambda x:x[1])
#print(sd)

for i in range (K) :
    print(sd[i][1])
    
    

 

색깔모으기

문제 백준링크 

풀이

이걸 초딩이 푼다고? 대단...미리 싸인받아놓고 싶다.

무향그래프의 사이클과 유향그래프의 진출차수를 활용.


from collections import defaultdict
import sys

N = int(sys.stdin.readline().rstrip())
A = []
B = []
for i in range(N):
    a, b = list(map(int, sys.stdin.readline().rstrip().split(' ')))
    A.append(a)
    B.append(b)

# deg:진출차수, g:무방향그래프
deg = defaultdict(int)
g = defaultdict(list)
colors = set()

for i in range(N):
    a = A[i]
    b = B[i]
    deg[a] += 1
    if a==b:
        continue
    # if a != b:
    #     deg[b] += 0
    g[a].append(b)
    g[b].append(a)
    colors.add(a)
    colors.add(b)

# print(deg)
# print(g)
# print(colors)

visited = set()
result = 0

def dfs(u, cycle_nodes):
    visited.add(u)
    cycle_nodes.append(u)
    for v in g[u]:
        if v not in visited:
            dfs(v, cycle_nodes)

for color in colors:
    if color not in visited:
        cycle_nodes = []
        dfs(color, cycle_nodes)
        #print(cycle_nodes)
        if len(cycle_nodes) == 1:
            print(0)
            #continue
            exit()
        outdeg_count = sum(1 for c in cycle_nodes if deg[c] >= 2)
        #print(outdeg_count)

        if outdeg_count >= 2:
            print(-1)
            exit()
        result += len(cycle_nodes) + 1  # 사이클 크기 + 1

print(result)

 

 

KOI 2024 1차대회 

등교 

문제 백준링크

풀이

쉬운문제 s + t가  x보다 작은 것 중 가장 큰것.

n, x = map(int, input().split(' '))
lst = []
for i in range(n):
    s, t = map(int, input().split(' '))
    if s+t > x:
        lst.append(-1)
    else:
        lst.append(s)

print(max(lst))

 

두배

문제 백준링크

풀이

반복문을 이용하면 시간초과. 

Math Library Log(), ceil()을 사용해 틀림.

내장 로그함수를 사용해 틀린 후 다시 풀어본 문제.

n = int(input())
a = list(map(int, input().split(' ')))
log = [0] * (250000+1)
_max = 20 # 2^max = 1,000,000 이상

def mylog(x, y):
    nx, ny = x, y

    for i in range(_max):
        nx *= 2

    for i in range(-_max, 0):
        if nx <= ny:
            return i
        nx /= 2

    for i in range(_max):
        if nx <= ny:
            return i
        ny *= 2
    return _max
    


for i in range(1, n):
    log[i] = mylog(a[i-1], a[i])

cnt = 0
for i in range(1, n):
    if log[i] > 0:
        cnt += log[i]
        log[i+1] += log[i]

print(cnt)

 

반품회수

문제 백준링크

풀이

일단 맨 오른쪽 끝으로 이동한 후 왼쪽으로 이동하며 처리. 

n = int(input())
x = list(map(int, input().split(' ')))
t = list(map(int, input().split(' ')))

tm = x[-1]
if tm < t[-1]:
    tm = t[-1]

for i in range(n-2, -1, -1):
    tm += x[i+1] - x[i]
    if tm < t[i]:
        tm += t[i] - tm
tm += x[0]

print(tm)

 

회의장소

문제 백준링크

풀이

import bisect
import sys

def count_in_range(lst, a, b):
    left = bisect.bisect_left(lst, a)
    right = bisect.bisect_right(lst, b)    
    return lst[left:right]

def get_tired(m):     
    # 집좌표 누적합, h[3]는 m[0] + m[1] + m[2].
    h = [0]
    for i in m:
        h.append(h[-1] + i)
    # h[i] = m[0] + m[1] + ... + m[i-1]

    total = h[-1]
    v = []        
    n = len(m)
    for i in range(n):
        # m[0] ~ m[i-1]까지의 합
        left_sum = h[i]
        # m[i] ~ m[n-1]까지의 합
        right_sum = total - h[i+1]
        
        cost = m[i] * i - left_sum + right_sum - m[i] * (n - i - 1)
        v.append(cost)    
    return v   

n, q = map(int, sys.stdin.readline().rstrip().split(' '))
x = list(map(int, sys.stdin.readline().rstrip().split(' ')))

for _ in range(q):
    l, r = map(int, sys.stdin.readline().rstrip().split(' '))
    m = count_in_range(x, l, r)
    #print(m)
    if len(m) <= 1:
        print(0)    
        continue
    v = get_tired(m)
    max_v = max(v)
    min_v = min(v)
    #print(max_v-min_v)
    sys.stdout.write(str(max_v-min_v) + '\n')
    

 

KOI 2023 2차대회 

불안정한 수열

문제 백준링크

풀이

N = int(input())
B = list(map(int, input().split(' ')))

cnt = 0
for i in range(N-1):
    if (B[i] + B[i+1])%2==1:
        cnt+=1

print(cnt+1)

 

 

KOI 2023 1차대회 

크림빵

문제 백준링크

풀이

n, k, p = map(int, input().split(' '))

lst = list(map(int, input().split(' ')))

s = 0

for i in range(n):
    c = 0
    for j in range(k):
        h = (i*k)+j
        if lst[h]==0:
            c+=1

    if c<p:
        s+=1
print(s)

 

대피소

문제 백준링크

풀이 

from itertools import combinations

def manhattan(a, b):
    return abs(a[0] - b[0]) + abs(a[1] - b[1])

def is_valid(houses, candidates, K, r):
    for shelters in combinations(candidates, K):        
        ok = True
        for h in houses:  # 각 집에 대해
            covered = False  # 이 집이 r 거리 내 대피소와 연결 가능한지 여부

            for s in shelters:  # 선택된 대피소들 중 하나와 비교
                if manhattan(h, s) <= r:  # 거리가 r 이하면
                    covered = True  # 이 집은 커버 가능함
                    break  # 더 볼 필요 없이 탈출

            if not covered:
                ok = False  # 이 집은 어떤 대피소와도 연결 안 됨
                break  # 하나라도 실패했으니 이 조합은 안 됨

        if ok:
            return True  # 하나라도 성공한 조합이 있다면 전체적으로 가능함

    # 모든 조합을 다 시도했지만 안 됨
    return False

def find_min_max_distance(houses, K):
    left, right = 0, 200_000
    answer = right

    while left <= right:
        mid = (left + right) // 2
        if is_valid(houses, houses, K, mid):
            answer = mid
            right = mid - 1
        else:
            left = mid + 1
    return answer

# 입력 처리
n, k = map(int, input().split())
houses = [tuple(map(int, input().split())) for _ in range(n)]
#print(houses)

# 결과 출력
print(find_min_max_distance(houses, k))

 

 

시간 날 때마다 문제, 해설을 추가할 계획입니다.

감사합니다.

댓글

이 블로그의 인기 게시물

Qt Designer 설치하기

파이썬을 활용한 PID 제어기 GUI 구현

PyQt5 기반 동영상 플레이어앱 만들기