
from bisect import bisect_left, bisect_right
array = [1,2,4,4,8]
x = 4
print(bisect_left(array,x))
print(bisect_right(array,x))
2
4
# 값이 [min_value, max_value]인 데이터의 개수를 반환하는 함수
def count_by_range(array, min_value, max_value):
right_index = bisect_right(array, max_value)
left_index = bisect_left(array, min_value)
return right_index - left_index
array = [1,2,3,3,3,3,4,4,8,9]
print(count_by_range(array,4,4))
print(count_by_range(array,-1,3))
2
6
문제설명
상근이는 나무 M미터가 필요하다. 정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고, 상근이는 새로 구입한 목재절단기를 이용해서 나무를 구할것이다. 목재절단기에 높이 H를 지정하면, 톱날이 땅으로부터 H미터 위로 올라간다. 따라서, 높이가 H보다 큰 나무는 H 위의 부분이 잘릴 것이고, 낮은 나무는 잘리지 않을 것이다. 예를 들어, 한 줄에 연속해있는 나무의 높이가 20, 15, 10, 17이라고 하자. 상근이가 높이를 15로 지정했다면, 나무를 자른 뒤의 높이는 15, 15, 10, 15가 될 것이고, 상근이는 길이가 5인 나무와 2인 나무를 들고 집에 갈 것이다. (총 7미터를 집에 들고 간다) 절단기에 설정할 수 있는 높이는 양의 정수 또는 0이다. 상근이는 환경에 매우 관심이 많기 때문에, 나무를 필요한 만큼만 집으로 가져가려고 한다. 이때, 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하시오.
입력조건
# 나무의 개수(N)와 필요한 나무의 최소 길이(M)을 입력
n, m = list(map(int, input().split()))
# 각 나무의 개별 높이 정보를 입력
array = list(map(int, input().split()))
# 이진 탐색을 위한 시작점과 끝점 설정
start = 0
end = max(array)
# 이진 탐색 수행 (반복적)
result = 0
while(start <= end):
total = 0
mid = (start + end) // 2
for x in array:
# 잘랐을 때의 나무의 길이 계산
if x > mid:
total += x - mid
# 나무의 길이가 부족한 경우 더 많이 자르기 (왼쪽 부분 탐색)
if total < m:
end = mid - 1
# 나무의 길이가 충분한 경우 덜 자르기 (오른쪽 부분 탐색)
else:
result = mid # 최대한 덜 잘랐을 때가 정답이므로, 여기에서 result에 기록
start = mid + 1
# 정답 출력
print(result)
15
문제설명
박성원이 캠프 때 쓸 N개의 랜선을 만들어야 하는데 너무 바빠서 영식이에게 도움을 청했다. 이미 오영식은 자체적으로 K개의 랜선을 가지고 있다. 그러나 K개의 랜선은 길이가 제각각이다. 박성원은 랜선을 모두 N개의 같은 길이의 랜선으로 만들고 싶었기 때문에 K개의 랜선을 잘라서 만들어야 한다. 예를 들어 300cm 짜리 랜선에서 140cm 짜리 랜선을 두 개 잘라내면 20cm는 버려야 한다. (이미 자른 랜선은 붙일 수 없다.) 편의를 위해 랜선을 자르거나 만들 때 손실되는 길이는 없다고 가정하며, 기존의 K개의 랜선으로 N개의 랜선을 만들 수 없는 경우는 없다고 가정하자. 그리고 자를 때는 항상 센티미터 단위로 정수길이만큼 자른다고 가정하자. N개보다 많이 만드는 것도 N개를 만드는 것에 포함된다. 이때 만들 수 있는 최대 랜선의 길이를 구하는 프로그램을 작성하시오.
입력조건
# 데이터 입력받기
k, n = 4, 11
lanes = [802, 743, 457, 539]
# 알고리즘 구현
# 랜선의 개수를 구하는 함수 (인자는 길이)
# 길이가 주어졌을때 몇개의 랜선을 만드는지 구하는 함수
def count_lanes(length):
count = 0
for lane in lanes:
count += lane // length
return count
# 이진 탐색을 위한 값 초기화
low, high = 1, max(lanes)
# 결과값 초기화
result = 0
# 이진탐색
while low <= high:
mid = (low + high) // 2
if count_lanes(mid) >= n: # n개 이상의 랜선을 만들수 있으면
result = mid # 가능한 길이 중 가장 큰 값 기록
low = mid + 1 # 더 길이를 시도하도록 (오른쪽 탐색)
else:
high = mid - 1 # 길이를 줄여서 다시 시도 (왼쪽 탐색)
# 결과 출력
print(result)
200
def fibo(x):
if x == 1 or x == 2:
return 1
return fibo(x - 1) + fibo(x - 2)
print(fibo(6))
## 피보나치 함수 (탑다운(메모이제이션))
# 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화
d = [0] * 100
# 피보나치 함수를 재귀함수로 구현
def fibo(x):
# 종료 조건(1 혹은 2일 때 1을 반환)
if x == 1 or x == 2:
return 1
# 이미 계산한 적 있는 문제라면 그대로 반환
if d[x] != 0:
return d[x]
# 아직 계산하지 않은 문제라면 점화식에 따라서 피보나치 결과 반환
d[x] = fibo(x - 1) + fibo(x - 2)
return d[x]
print(fibo(99))
## 피보나치 함수 (바텀업)
# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
d = [0] * 100
# 1,2의 피보나치 수는 1
d[1] = 1
d[2] = 1
n = 99
# 피보나치 함수를 반복문으로 구현 (바텀업)
for i in range(3, n + 1):
d[i] = d[i-1] + d[i-2]
print(d[99])
f10
f9 f15
f3 f8 f4
f1 f2
# N 입력 받기
n = 10
# 코드 구현
dp = [0] * 1000001 # DP테이블 (배열) 생성
# DP 프로그래밍 (바텀업)
# dp 초기값 세팅 << 최적의 해만 저장
dp[1] = 1
dp[2] = 1
dp[3] = 1
# 모든 n값에 대하여 값 저장
for i in range(4, n+1):
# 1을 빼는 경우
dp[i] = dp[i-1] + 1
# 2를 나누는 경우
if i % 2 == 0 :
dp[i] = min(dp[i], dp[i//2] + 1)
if i % 3 == 0:
dp[i] = min(dp[i], dp[i//3] + 1)
# 결과 출력
print(dp[n])
3
def min_operations_to_one(n):
dp = [0] * (n + 1) # dp[i]는 i를 1로 만드는 최소 연산 횟수를 저장
for i in range(2, n + 1):
dp[i] = dp[i - 1] + 1 # 1을 빼는 연산
if i % 2 == 0:
dp[i] = min(dp[i], dp[i // 2] + 1) # 2로 나누는 연산
if i % 3 == 0:
dp[i] = min(dp[i], dp[i // 3] + 1) # 3으로 나누는 연산
return dp[n]
min_operations_to_one(10)
3
# 노드의 개수, 간선의 개수를 입력받기
n, m = 6, 11
# 시작 노드 번호를 입력받기
start = 1
# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
abc = [[1, 2, 2], [1, 3, 5], [1, 4, 1], [2, 3, 3],
[2, 4, 2], [3, 2, 3], [3, 6, 5], [4, 3, 3],
[4, 5, 1], [5, 3, 1], [5, 6, 2]]
## 다익스트라 알고리즘
inf = int(1e9) # 무한을 의미하는 값으로 10억을 설정
# # 노드의 개수, 간선의 개수를 입력받기
# n, m = map(int, input().split())
# # 시작 노드 번호를 입력받기
# start = int(input())
# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
graph = [[] for i in range(n + 1)]
# 방문한 적이 있는지 체크하는 목적의 리스트를 만들기
visited = [False] * (n + 1)
# 최단 거리 테이블을 모두 무한으로 초기화
distance = [inf] * (n + 1)
# 모든 간선 정보를 입력받기
for a, b, c in abc:
# A에서 B로 가는 비용은 C라고 설정
graph[a].append((b, c))
# 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환
def get_smallest_node():
min_value = inf
index = 0 # 가장 최단 거리가 짧은 노드(인덱스)
for i in range(1, n + 1):
if distance[i] < min_value and not visited[i]:
min_value = distance[i]
index = i
return index
def dijkstra(start):
# 시작 노드에 대해서 초기화
distance[start] = 0
visited[start] = True
for j in graph[start]:
distance[j[0]] = j[1]
# 시작 노드를 제외한 전체 n - 1개의 노드에 대해 반복
for i in range(n - 1):
# 현재 최단 거리가 가장 짧은 노드를 꺼내서, 방문 처리
now = get_smallest_node()
visited[now] = True
# 현재 노드와 연결된 다른 노드를 확인
for j in graph[now]:
cost = distance[now] + j[1]
# 현재 노드를 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우
if cost < distance[j[0]]:
distance[j[0]] = cost
# 다익스트라 알고리즘을 수행
dijkstra(start)
# 모든 노드로 가기 위한 최단 거리를 출력
for i in range(1, n + 1):
# 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
if distance[i] == inf:
print("INFINITY")
# 도달할 수 있는 경우 거리를 출력
else:
print(distance[i])
0
2
3
1
2
4
inf = int(1e9) # 무한을 의미하는 값으로 10억을 설정
# 노드의 개수 및 간선의 개수를 입력받기
n = int(input())
m = int(input())
# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화
graph = [[inf] * (n + 1) for _ in range(n + 1)]
# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
for a in range(1, n + 1):
for b in range(1, n + 1):
if a == b:
graph[a][b] = 0
# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
for _ in range(m):
# A에서 B로 가는 비용은 C라고 설정
a, b, c = map(int, input().split())
graph[a][b] = c
# 플로이드 워셜 알고리즘을 수행
for k in range(1, n + 1):
for a in range(1, n + 1):
for b in range(1, n + 1):
graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
# 수행된 결과를 출력
for a in range(1, n + 1):
for b in range(1, n + 1):
# 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
if graph[a][b] == inf:
print("INFINITY", end=" ")
# 도달할 수 있는 경우 거리를 출력
else:
print(graph[a][b], end=" ")
print()
4
7
1 2 4
1 4 6
2 1 3
2 3 7
3 1 5
3 4 4
4 3 2
문제설명
케빈 베이컨의 6단계 법칙에 의하면 지구에 있는 모든 사람들은 최대 6단계 이내에서 서로 아는 사람으로 연결될 수 있다. 케빈 베이컨 게임은 임의의 두 사람이 최소 몇 단계 만에 이어질 수 있는지 계산하는 게임이다. 예를 들면, 전혀 상관없을 것 같은 인하대학교의 이강호와 서강대학교의 민세희는 몇 단계만에 이어질 수 있을까? 천민호는 이강호와 같은 학교에 다니는 사이이다. 천민호와 최백준은 Baekjoon Online Judge를 통해 알게 되었다. 최백준과 김선영은 같이 Startlink를 창업했다. 김선영과 김도현은 같은 학교 동아리 소속이다. 김도현과 민세희는 같은 학교에 다니는 사이로 서로 알고 있다. 즉, 이강호-천민호-최백준-김선영-김도현-민세희 와 같이 5단계만 거치면 된다. 케빈 베이컨은 미국 헐리우드 영화배우들 끼리 케빈 베이컨 게임을 했을때 나오는 단계의 총 합이 가장 적은 사람이라고 한다. 오늘은 Baekjoon Online Judge의 유저 중에서 케빈 베이컨의 수가 가장 작은 사람을 찾으려고 한다.
입력조건
3.출력조건 : 유저 중에서 케빈 베이컨의 수가 가장 작은 사람을 출력한다. 그런 사람이 여러 명일 경우에는 번호가 가장 작은 사람을 출력한다. (예시 : 3)
# 데이터 입력받기
n,m = 5,5
friends = [(1,3), (1,4), (4,5), (4,3), (3,2)]
# 필요한 자료 초기화
inf = int(1e9)
graph = [[inf] *(n+1) for _ in range(n+1)]
# 친구관계를 나타내는 정보 업데이트 (친구라면 1)
for a,b in friends:
graph[a][b] = 1
graph[b][a] = 1
# 자기자신의 경우는 0
for a in range(1, n+1):
for b in range(1, n+1):
if a==b:
graph[a][b] = 0
# 알고리즘 구현
for k in range(1, n+1):
for a in range(1, n+1):
for b in range(1, n+1):
graph[a][b] = min(graph[a][b], graph[a][k]+graph[k][b])
# 출력
result = 0
min_value = n*m
for a in range(1, n+1):
links = [x for x in graph[a] if x!=inf]
if sum(links) < min_value:
min_value = sum(links)
result = a
print(result)
3