Compare commits
106 Commits
2d2a6f36fb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8460030a1f | ||
|
|
2d5535fe97 | ||
|
|
572fb9b1ce | ||
|
|
f336fd8e5f | ||
|
|
8e080abe52 | ||
|
|
32ec66e6a9 | ||
| fc2523e4ae | |||
| fbbd5d3809 | |||
|
|
2b698b487e | ||
|
|
8e68290fe3 | ||
|
|
ae7df30365 | ||
|
|
4e13009885 | ||
|
|
eded08a5d1 | ||
|
|
090f779d52 | ||
|
|
992da4d0f5 | ||
|
|
7429d960d2 | ||
|
|
7f235e6836 | ||
|
|
5d300435a5 | ||
|
|
f79594f871 | ||
|
|
a1c9fe6798 | ||
|
|
3222e78317 | ||
|
|
5d7eebc8f1 | ||
|
|
3a802d35c3 | ||
|
|
97cf2d9e54 | ||
|
|
30ee1143fb | ||
|
|
a62fcf41a3 | ||
|
|
77f4339bbf | ||
|
|
87e7ad2fcb | ||
|
|
8f84a61a23 | ||
|
|
2dbd06f4f6 | ||
|
|
81fd3ef46e | ||
|
|
f28354b79c | ||
|
|
e84f83b0b7 | ||
|
|
159c3878a6 | ||
|
|
618f6dc8bf | ||
|
|
ae9db766c4 | ||
| 633494610a | |||
| bd846871de | |||
| 409f293091 | |||
| b0ec14828b | |||
| 32616725c5 | |||
| e5f5c64f26 | |||
| 6ad8ca72e6 | |||
| fc52790b41 | |||
| 5b3ecdc596 | |||
| e35a7cbbaf | |||
| 4118f8f7a0 | |||
| 7c30191f63 | |||
| 93ea0d98a9 | |||
| 4d7b40c0fd | |||
| 45d79b7bd0 | |||
| d0d8869b5c | |||
| 633ec60c73 | |||
| edb54cb0a4 | |||
| 2e1b508e92 | |||
| 7bcb4dfdc4 | |||
| 3777344b56 | |||
| 9dafd92505 | |||
| c902220c1d | |||
| 0e8e68d12f | |||
| 4aebd20cf5 | |||
| ecb877621f | |||
| 630d1141c1 | |||
| 88ce2a45b1 | |||
| 54307abd2a | |||
| f6df1e7883 | |||
| 3c5ddbd8dc | |||
| 1da1eeb10c | |||
| 21c4366e58 | |||
| 524b9d7b4a | |||
| b5fc24cbce | |||
| 28a212e4e7 | |||
| e1e7033acc | |||
| 3ca18fe457 | |||
| 5d4a3bd574 | |||
| cd9ef4df24 | |||
| 20a21cd6b0 | |||
| 867aab2d5b | |||
| b46632a93b | |||
| 7509610c77 | |||
| 7f7c0475eb | |||
| 158d5b7f23 | |||
| 279e6eb00f | |||
| dddc4668be | |||
| c786856f03 | |||
| 586c1d7130 | |||
| 10ac4d6d2e | |||
| 13f1bcff12 | |||
| f0cd496882 | |||
| f8d5ba62b1 | |||
| b287d194af | |||
| 1129cfd5d3 | |||
| 2f4757f560 | |||
| 7bba77f228 | |||
| c679c7f481 | |||
| 70a785013a | |||
| 472bac7e4e | |||
| 35eecf2294 | |||
| 66e9cc1b83 | |||
| 0d13cbf915 | |||
| 4eb1c87b5e | |||
| 956e00feb1 | |||
|
|
9bdbaec471 | ||
|
|
944995535d | ||
|
|
a8b8451e08 | ||
|
|
dbb22d9092 |
51
14003-p5.py
Normal file
51
14003-p5.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# 가장 긴 증가하는 부분 수열 5
|
||||
|
||||
import sys
|
||||
from bisect import bisect_left
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = list(map(int, input().rstrip().split()))
|
||||
parent = [-1] * (n)
|
||||
|
||||
result = [lst[0]]
|
||||
result_idx = [0]
|
||||
for i in range(1, n):
|
||||
if lst[i] > result[-1]:
|
||||
parent[i] = result_idx[-1]
|
||||
result.append(lst[i])
|
||||
result_idx.append(i)
|
||||
continue
|
||||
idx = bisect_left(result, lst[i])
|
||||
if result[idx] != lst[i]:
|
||||
result[idx] = lst[i]
|
||||
result_idx[idx] = i
|
||||
if idx != 0:
|
||||
parent[i] = result_idx[idx-1]
|
||||
|
||||
answer = [result[-1]]
|
||||
parent_idx = parent[result_idx[-1]]
|
||||
while parent_idx != -1:
|
||||
answer.append(lst[parent_idx])
|
||||
parent_idx = parent[parent_idx]
|
||||
|
||||
print(len(answer))
|
||||
print(*answer[::-1])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 2분 ㅋㅋ
|
||||
|
||||
시간 복잡도: 14002와 같게 모든 수에 대해. 이분 탐색을 진행하기 때문에 O(nlogn)이다.
|
||||
|
||||
해설: 14002번(가장 긴 증가하는 부분 수열 4) 답을 그대로 가져와서 binary_search를 직접 구현하지 않고, bisect를 활용해서 구현하였다.
|
||||
내가 들어갈 자리는 나보다 처음으로 큰 녀석의 자리이기 때문에 사실상 왼쪽으로 들어간다고 생가하면 된다.(오른쪽은 제거하지만..)
|
||||
따라서 bisect_left를 활용하였다.
|
||||
또한 bisect_left에는 리스트 원소들이 tuple이면 안되기 때문에, result_idx라는 리스트를 따로 만들어서 진행하였다.
|
||||
"""
|
||||
64
1504-g4.py
Normal file
64
1504-g4.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# 특정한 최단 경로
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def get_short(start, g, n):
|
||||
dp = [float('inf')] * (n+1)
|
||||
pq = [(0, start)]
|
||||
|
||||
dp[start] = 0
|
||||
while pq:
|
||||
dist, now = heapq.heappop(pq)
|
||||
|
||||
if dist > dp[now]:
|
||||
continue
|
||||
|
||||
for nxt, v in g[now]:
|
||||
nxt_dist = dist + v
|
||||
if nxt_dist < dp[nxt]:
|
||||
dp[nxt] = nxt_dist
|
||||
heapq.heappush(pq, (nxt_dist, nxt))
|
||||
|
||||
return dp
|
||||
|
||||
def solution():
|
||||
n, e = map(int, input().rstrip().split())
|
||||
|
||||
g = {i: [] for i in range(1, n+1)}
|
||||
for i in range(e):
|
||||
a, b, c = map(int, input().rstrip().split())
|
||||
g[a].append((b,c))
|
||||
g[b].append((a,c))
|
||||
|
||||
v1, v2 = map(int, input().rstrip().split())
|
||||
|
||||
start_1 = get_short(1, g, n)
|
||||
start_v1 = get_short(v1, g, n)
|
||||
start_v2 = get_short(v2, g, n)
|
||||
|
||||
result = min(start_1[v1] + start_v1[v2] + start_v2[n], start_1[v2] + start_v2[v1] + start_v1[n])
|
||||
|
||||
if result == float('inf'):
|
||||
result = -1
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: 간선에 연결된 각 정점에 대해 모든 연결된 선을 확인하기 때문에 그냥 간선의 길이만큼 본다고 생각하면 된다.
|
||||
이때, 간선 하나를 보고 heap 조작을 한번 하기 때문이 loge이다.
|
||||
따라서 전체 시간복잡도는 O(eloge)이다.
|
||||
|
||||
해설: 1 -> v1 -> v2 -> n, 1 -> v2 -> v1 -> n 중 더 짧은 것을 구하면 된다.
|
||||
1, v1, v2 기준으로 다 구하면 된다.
|
||||
다익스트라는 하던대로 구현하면 완료.
|
||||
"""
|
||||
47
1654-s2.py
Normal file
47
1654-s2.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# 랜선 자르기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def binary_search(l, r, lan_lst, target):
|
||||
result = 0
|
||||
while l <= r:
|
||||
count = 0
|
||||
mid = (l+r)//2
|
||||
for lan in lan_lst:
|
||||
count += (lan // mid)
|
||||
|
||||
if count >= target:
|
||||
l = mid+1
|
||||
result = mid
|
||||
else:
|
||||
r = mid-1
|
||||
return result
|
||||
|
||||
def solution():
|
||||
k, n = map(int, input().rstrip().split())
|
||||
|
||||
max_len = 0
|
||||
lan_lst = [0] * k
|
||||
for i in range(k):
|
||||
lan_lst[i] = int(input().rstrip())
|
||||
max_len = max(max_len, lan_lst[i])
|
||||
|
||||
result = binary_search(l=1, r=max_len+1, lan_lst=lan_lst, target=n)
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간
|
||||
|
||||
시간 복잡도: 1부터 가장 큰 랜선 길이까지의 범위에서 이분탐색을 진행하므로 O(log(2^31-1))이고, 이분탐색을 할 때마다 k개의 랜선을 잘라보기 때문에 O(klogn)이다.
|
||||
|
||||
해설: 최대 길이를 찾는 것이기 때문에 주어진 랜선 중 가장 긴 길이부터 아래로 내려가면서 n개가 나오는 첫 지점을 찾으면 된다.
|
||||
근데 이렇게 하면 랜선의 길이가 최대 2^31-1이므로 너무 오래 걸린다.
|
||||
마침 수직선이기 때문에 이분탐색을 하면 되겠다는 생각을 했고, 이렇게 최적화 문제를 결정문제로 바꿔서 푸는 것을 파라메트릭 서치라고 한다.
|
||||
이분 탐색 구현은 count가 n보다 크면 일단 답 후보로 넣어놓고, l을 mid+1로 옮겼고, 반대의 상황일 때는 답 후보로 넣지 않고, r을 mid-1로 했다.
|
||||
"""
|
||||
21
template.py
Normal file
21
template.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# 제목
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간:
|
||||
|
||||
시간 복잡도:
|
||||
|
||||
해설:
|
||||
"""
|
||||
30
workbook_7319/bronze/2748-b1.py
Normal file
30
workbook_7319/bronze/2748-b1.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# 피보나치 수 2
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
dp = [0] * 100
|
||||
dp[0] = 0
|
||||
dp[1] = 1
|
||||
|
||||
for i in range(2, n+1):
|
||||
dp[i] = dp[i-1] + dp[i-2]
|
||||
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 3분
|
||||
|
||||
시간 복잡도: n까지 dp 테이블을 채우면 되므로 O(n)이다.
|
||||
|
||||
해설: i번째 칸을 채우기 위해서는 i-1, i-2번째 값을 알아야하기 때문에 dp테이블에 이전 값들을 기록해가면서 현재 값을 채우면 된다.
|
||||
"""
|
||||
54
workbook_7319/gold/12852-g5.py
Normal file
54
workbook_7319/gold/12852-g5.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# 1로 만들기 2
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
dp = [float('inf')]*(n+1)
|
||||
dp[n] = (0, n)
|
||||
|
||||
ways = [3, 2]
|
||||
|
||||
for i in range(n-1, 0, -1):
|
||||
min_count = float('inf')
|
||||
min_from = -1
|
||||
for way in ways:
|
||||
before = i * way
|
||||
if before > n:
|
||||
continue
|
||||
if min_count > dp[before][0]:
|
||||
min_count = dp[before][0]
|
||||
min_from = before
|
||||
before = i + 1
|
||||
if before > n:
|
||||
continue
|
||||
if min_count > dp[before][0]:
|
||||
min_count = dp[before][0]
|
||||
min_from = before
|
||||
|
||||
dp[i] = (min_count+1, min_from)
|
||||
|
||||
result = [1]
|
||||
idx = 1
|
||||
while idx < n:
|
||||
idx = dp[idx][1]
|
||||
result.append(idx)
|
||||
|
||||
print(dp[1][0])
|
||||
print(*result[::-1])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: dp 테이블 채우고 역추적까지 O(n)이다.
|
||||
|
||||
해설: 1463(1로 만들기 문제)번에서 과정을 출력하는 과정이 추가되었다. 이는 dp 테이블을 채울 때, 어디서 왔는지만 기록해주면 마지막에 역추적을 하면 된다.
|
||||
"""
|
||||
64
workbook_7319/gold/14002-g4.py
Normal file
64
workbook_7319/gold/14002-g4.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# 가장 긴 증가하는 부분 수열 4
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def binary_search(result, target):
|
||||
l, r = 0, len(result)-1
|
||||
idx = len(result)
|
||||
while l <= r:
|
||||
mid = (l+r)//2
|
||||
|
||||
if result[mid][0] >= target:
|
||||
idx = mid
|
||||
r = mid - 1
|
||||
else:
|
||||
l = mid + 1
|
||||
|
||||
return idx
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = list(map(int, input().rstrip().split()))
|
||||
parent = [-1] * (n)
|
||||
|
||||
result = [(lst[0], 0)]
|
||||
for i in range(1, n):
|
||||
if lst[i] > result[-1][0]:
|
||||
parent[i] = result[-1][1]
|
||||
result.append((lst[i], i))
|
||||
continue
|
||||
idx = binary_search(result, lst[i])
|
||||
if result[idx][0] != lst[i]:
|
||||
result[idx] = (lst[i], i)
|
||||
if idx != 0:
|
||||
parent[i] = result[idx-1][1]
|
||||
|
||||
answer = [result[-1][0]]
|
||||
parent_idx = parent[result[-1][1]]
|
||||
while parent_idx != -1:
|
||||
answer.append(lst[parent_idx])
|
||||
parent_idx = parent[parent_idx]
|
||||
|
||||
print(len(answer))
|
||||
print(*answer[::-1])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 39분
|
||||
|
||||
시간 복잡도: 하나의 수에 대해. 이진탐색을 진행하기 때문에 O(nlogn)이다.
|
||||
|
||||
해설: 가장 긴 증가하는 부분 수열 문제에서 수열 자체를 알아야 하는 문제이다.
|
||||
기존에 하던 방식은 개수만 원했기 때문에 결과 리스트에 업데이트 하면서 진행했다.
|
||||
하지만 결과 리스트에 있는 것들은 그것 자체가 수열이 아니고, result[i]는 i개의 증가하는 수열들의 맨 뒤 값 중 가장 작은 값이다.
|
||||
따라서 result를 업데이트 하면서 현재 보는 수의 바로 이전 수를 기록해놔야 한다.(parent 기록)
|
||||
바로 이전 수는 result에서 binary_search를 했을 때, 본인이 들어갈 idx의 앞에 있는 수가 내가 맨 뒤일때 최선의 수이다.
|
||||
따라서 그 수의 idx를 계속 기록하면 된다.
|
||||
마지막에 result[-1]의 parent를 계속 역추적 하면 하나의 수열이 완성된다.
|
||||
"""
|
||||
46
workbook_7319/gold/15486-g5.py
Normal file
46
workbook_7319/gold/15486-g5.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# 퇴사 2
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
t = [0] * (n+1)
|
||||
p = [0] * (n+1)
|
||||
|
||||
for i in range(1, n+1):
|
||||
t[i], p[i] = map(int, input().rstrip().split())
|
||||
|
||||
dp = [0] * (n+2)
|
||||
max_p = 0
|
||||
for i in range(1, n+1):
|
||||
max_p = max(max_p, dp[i])
|
||||
|
||||
nxt = i+t[i]
|
||||
if nxt <= n+1:
|
||||
dp[nxt] = max(dp[nxt], max_p+p[i])
|
||||
|
||||
print(max(max_p, dp[n+1]))
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 몰라
|
||||
|
||||
시간 복잡도: 과거에서 미래 한 시점에만 업데이트를 하기 때문에 n 테이블을 다 채우기만 하면 되므로 O(n)이다.
|
||||
|
||||
해설: 14501(퇴사)번 문제는 n이 작았기 때문에 dp[i]를 채울 때 이전 값들 중에 i로 올 수 있는 것들을 전부 보고 최대값을 구하는
|
||||
O(n^2)로 해도 괜찮았다.
|
||||
근데 이번 문제는 n이 많이 크기 때문에 기존 방식은 안된다.
|
||||
따라서 미래에서 과거를 보는 것이 아닌 과거에서 미래로 값을 놓는 방식을 선택했다.(답 보고 알았음)
|
||||
i를 볼 때 지금까지의 최대 수익을 계속 기록해놓으면서 i에서 상담을 했다고 쳤을 때,
|
||||
상담이 끝나는 날(nxt)에 i에 상담을 한 경우(max_p + p[i])와 더 과거에서 온 이력(dp[nxt])중 최대를 비교해서 갱신한다.
|
||||
이렇게 기록해놓으면 미래에는 과거에서 이 미래까지 온 최선의 경우의 수를 이미 가지고 있고,
|
||||
이것과 별개로 여기서 상담을 하지 않았을 때 최대 수익도 가지고 있다.
|
||||
이 둘을 계속 비교해가며 최대 수익을 갱신하고, 마지막에는 n+1날까지 온 최선의 수와 전체 최대 수익을 비교하여 마무리 한다.
|
||||
max_p = max(max_p, dp[n+1])은 하지 않았었기 때문.
|
||||
"""
|
||||
48
workbook_7319/gold/2240-g4.py
Normal file
48
workbook_7319/gold/2240-g4.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# 자두나무
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t, w = map(int, input().rstrip().split())
|
||||
|
||||
plum = [0] * (t+1)
|
||||
for i in range(1, t+1):
|
||||
plum[i] = int(input().rstrip())
|
||||
|
||||
dp = [[0] * (t+1) for _ in range(w+1)]
|
||||
|
||||
for i in range(1, t+1):
|
||||
dp[0][i] = dp[0][i-1]
|
||||
if plum[i] == 1:
|
||||
dp[0][i] += 1
|
||||
|
||||
for i in range(1, w+1):
|
||||
for j in range(1, t+1):
|
||||
dp[i][j] = max(dp[i][j-1], dp[i-1][j-1])
|
||||
if (plum[j] == 1 and i%2 == 0) or (plum[j] == 2 and i%2 == 1):
|
||||
dp[i][j] += 1
|
||||
|
||||
|
||||
result = 0
|
||||
for i in range(w+1):
|
||||
result = max(result, dp[i][t])
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: w*t의 테이블을 채워야 하기 때문에 O(w*t)이다.
|
||||
|
||||
해설: 현재의 상황은 몇번째 이동한 상황인지로 나뉘고, w만큼 이동했을 때 t초의 상황은 이번에 움직였거나, 이번에 안 움직였거나이다.
|
||||
따라서 dp[w][t] = max(dp[w][t-1], dp[w-1][t-1]) 이다.
|
||||
이때, w가 홀수면 2번, 짝수면 1번 나무에 있는 것이므로 t초에 떨어질 나무와 w의 홀짝 여부가 맞으면 +1을 해줘야한다.
|
||||
그리고 t초의 최대값은 이동을 얼마나 했을 때인지 모르기 때문에 마지막에 t초의 전체 w에 대해 최대값을 구해야한다.
|
||||
"""
|
||||
32
workbook_7319/gold/2293-g4.py
Normal file
32
workbook_7319/gold/2293-g4.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# 동전 1
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
|
||||
dp = [0] * (k+1)
|
||||
dp[0] = 1
|
||||
|
||||
for _ in range(n):
|
||||
coin = int(input().rstrip())
|
||||
for i in range(coin, k+1):
|
||||
dp[i] = dp[i-coin] + dp[i]
|
||||
|
||||
print(dp[k])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 13분
|
||||
|
||||
시간 복잡도: 동전 개수(n)만큼 k 길이의 테이블을 업데이트 해야하기 때문에 O(n*k)이다.
|
||||
|
||||
해설: 조합 조건으로 여러 동전을 활용해서 k 값을 만들어야 한다.
|
||||
이는 순서를 정해줘야 하기 때문에 동전을 하나씩 쓰면서 전체 dp를 순회해야 한다.
|
||||
1, 2, 5의 동전이 있다면 1 썼을 때 전체 dp, 2도 썼을 때 전체 dp 이런식으로.. (동전 사용 순서는 상관없다. 조합이니까 하나로만 정해지면 됨)
|
||||
"""
|
||||
49
workbook_7319/gold/2302-g5.py
Normal file
49
workbook_7319/gold/2302-g5.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# 극장 좌석
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
m = int(input().rstrip())
|
||||
|
||||
vip = [0] * (n+1)
|
||||
for _ in range(m):
|
||||
vip[int(input().rstrip())] = 1
|
||||
|
||||
dp = [0] * (n+1)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
for i in range(2, n+1):
|
||||
if vip[i] or vip[i-1]:
|
||||
dp[i] = dp[i-1]
|
||||
else:
|
||||
dp[i] = dp[i-1] + dp[i-2]
|
||||
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 16분
|
||||
|
||||
시간 복잡도: n개의 dp 테이블을 채우면 되기 때문에 O(n)이다.
|
||||
|
||||
해설: dp[i]를 i번 좌석까지 왔을 때 경우의 수라고 하자.
|
||||
i에 같은 번호가 잘 앉거나, 옆으로 이동하거나 2가지의 경우가 있다.
|
||||
i가 잘 앉은 경우에는 이전에서 변동이 없기 때문에 dp[i-1]을 하면된다.
|
||||
i가 옆으로 이동한 경우에는 왼쪽과 오른쪽 이동이 있는데, dp 테이블을 오른쪽으로 채워가기 때문에 오른쪽으로 이동하는 것은 지금 세지말자.
|
||||
그러면 i는 i-1자리로 이동할 수 있다. 그럼 i-1에 있는 애는 어디로 갈까? 반드시 i와 스왑을 해야한다.
|
||||
왜 why? 한쪽으로 계속 미는 방식으로 앉으면 마지막 사람은 앉을 곳이 없기 때문에 이 문제는 무조건 스왑이다.
|
||||
그렇기 때문에 오른쪽 이동은 dp[i+1]에서 왼쪽으로 스왑할때 책임져 줄 것이다.
|
||||
아무튼 i, i-1 자리가 바뀌었기 때문에 dp[i-2] 상황에서 새로운 경우가 발생한 것이다.
|
||||
따라서 dp[i] = dp[i-1] + dp[i-2]이다.
|
||||
이때 주의할 점은 vip인데, vip는 이동할 수 없고 무조건 본인 자리에 앉아야 하기 때문에 dp[i] = dp[i-1]이 된다.
|
||||
또한 우리는 왼쪽으로의 이동만 보기로 했기 때문에 vip의 오른쪽에 있는 사람도 왼쪽으로 이동을 할 수 없다.
|
||||
따라서 그 사람도 dp[i] = dp[i-1]이다.
|
||||
"""
|
||||
33
workbook_7319/silver/1003-s3.py
Normal file
33
workbook_7319/silver/1003-s3.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# 피보나치 함수
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
dp = [0] * 50
|
||||
dp[0] = (1, 0)
|
||||
dp[1] = (0, 1)
|
||||
|
||||
for i in range(2, 50):
|
||||
dp[i] = (dp[i-1][0]+dp[i-2][0], dp[i-1][1]+dp[i-2][1])
|
||||
|
||||
|
||||
for _ in range(t):
|
||||
k = int(input().rstrip())
|
||||
print(*dp[k])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 15분
|
||||
|
||||
시간 복잡도: n은 40보다 작다고 했기 때문에 dp테이블을 대략 50까지만 채우면 되므로 O(n)이다.
|
||||
|
||||
해설: 현재 보는 수는 결국 1개 전과, 2개 전에 사용했던 0, 1의 개수의 합이므로 dp 테이블을 만들어서 계속 채워나가면 된다.
|
||||
"""
|
||||
44
workbook_7319/silver/10844-s1.py
Normal file
44
workbook_7319/silver/10844-s1.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# 쉬운 계단 수
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
MOD = 1000000000
|
||||
|
||||
dp = [[1]*10 for _ in range(n)]
|
||||
dp[0][0] = 0
|
||||
|
||||
for i in range(1, n):
|
||||
for j in range(10):
|
||||
if i == 1 and j == 1:
|
||||
dp[i][j] = dp[i-1][j+1]
|
||||
continue
|
||||
if j == 0:
|
||||
dp[i][j] = dp[i-1][j+1]
|
||||
elif j == 9:
|
||||
dp[i][j] = dp[i-1][j-1]
|
||||
else:
|
||||
dp[i][j] = (dp[i-1][j-1] + dp[i-1][j+1])%MOD
|
||||
|
||||
print(sum(dp[n-1])%MOD)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: n*10 칸을 채워야하기 때문에 O(10n)이다.
|
||||
|
||||
해설: dp[i][j]는 i번째 자리수가 j로 끝날때 경우의 수이다.
|
||||
이전 행의 앞뒤에서만 올 수 있으므로, dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1]이다.
|
||||
0과 9는 각각 오른쪽과 왼쪽에서만 올 수 있고, 두번째 행에서 1은 0으로 시작할 수 없기 때문에 오른쪽에서만 와야한다.
|
||||
위 조건 그대로 코드로 구현한 뒤 mod로 나머지들만 계속 업데이트해가면 된다.
|
||||
마지막 수는 어떤 숫자든 가능하기 때문에 마지막 행의 모든 값을 더한 후 mod해서 답을 구한다.
|
||||
mod 공식은 1904 풀이를 확인하자.
|
||||
"""
|
||||
33
workbook_7319/silver/11052-s1.py
Normal file
33
workbook_7319/silver/11052-s1.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# 카드 구매하기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = [0] + list(map(int, input().rstrip().split()))
|
||||
|
||||
dp = lst[:]
|
||||
dp[1] = lst[1]
|
||||
|
||||
for i in range(2, n+1):
|
||||
for j in range(i-1, 0, -1):
|
||||
dp[i] = max(dp[i], dp[j]+lst[i-j])
|
||||
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: O(n^2)이다.
|
||||
|
||||
해설: dp[i]는 카드 i개를 모으고자 할때, 최대값이라고 하자.
|
||||
i개를 모으기 위해 i개보다 작은 수들에서 i로 올 수 있는 모든 경우의 수를 보고 최대값을 선택한다.
|
||||
"""
|
||||
54
workbook_7319/silver/11053-s2.py
Normal file
54
workbook_7319/silver/11053-s2.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# 가잔 긴 증가하는 부분 수열
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def binary_search(target, lis):
|
||||
l, r = 0, len(lis)
|
||||
while l < r:
|
||||
mid = (l+r)//2
|
||||
|
||||
if lis[mid] >= target:
|
||||
r = mid
|
||||
else:
|
||||
l = mid + 1
|
||||
|
||||
return l
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = list(map(int, input().rstrip().split()))
|
||||
|
||||
lis = []
|
||||
|
||||
for k in lst:
|
||||
if not lis or k > lis[-1]:
|
||||
lis.append(k)
|
||||
continue
|
||||
lis[binary_search(k, lis)] = k
|
||||
|
||||
print(len(lis))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 10분
|
||||
|
||||
시간 복잡도: 내 풀이는 모든 수를 보는데 그 수가 lis에서 들어갈 자리를 이분탐색으로 확인하기 때문에 O(nlogn)이다.
|
||||
|
||||
해설: 원래는 11055(가장 큰 증가하는 부분수열)번처럼 하나의 수를 볼때 앞에 나온 수중에 본인보다 작은 수의 dp 값을 보고 거기에 +1한 값의 최대가
|
||||
본인을 포함한 증가하는 수열의 길이이다. 근데 이것도 O(n^2)이다.
|
||||
따라서 나는 길이만 알면 되기 때문에 좀 더 시간을 줄여보았다.
|
||||
각 숫자를 순서대로 보면서 lis라는 리스트에 최대한 작은 수들을 넣는 것이다.
|
||||
예를 들어, [1, 5, 8] 이렇게 있을 때, 지금 보는 수가 3이라면 5대신 3으로 바꿔끼면 된다.
|
||||
이렇게 되면 3이 나중에 나온건데, 8이 아직도 있으니까 헷갈릴 수 있다.
|
||||
하지만 이건 lis[i]를 i개의 길이에서 가장 작은 녀석이라고 생각하면 된다.
|
||||
그럼 lis[2]는 2개짜리 수열 중에 제일 큰 놈의 최소가 3으로 됐을 뿐이고, lis[3]은 3개짜리 수열 중에 제일 큰 놈의 최소가 8일 뿐이다.
|
||||
이렇게 진행을 하고 lis[-1]보다 큰 놈이 들어오면 그냥 뒤에 붙이면 된다.
|
||||
이렇게 하면 원래 수열은 모르지만(복원하려면 따로 기록해야 한다.) 최대 길이를 알 수 있다.
|
||||
"""
|
||||
29
workbook_7319/silver/11055-s2.py
Normal file
29
workbook_7319/silver/11055-s2.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# 가장 큰 증가하는 부분 수열
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = list(map(int, input().rstrip().split()))
|
||||
dp = lst[:]
|
||||
|
||||
for i in range(1, n):
|
||||
dp[i] = max([dp[j]+lst[i] for j in range(i-1, -1, -1) if lst[j] < lst[i]] + [lst[i]])
|
||||
|
||||
print(max(dp))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: 하나의 값을 볼때 내 앞에 있는 값들을 다 확인해봐야하기 때문에 O(n^2)이다.
|
||||
|
||||
해설: 현재 보는 값보다 앞에 나온 작은 놈들의 dp 값에 나를 더하면, 이는 앞에 나온 수열 중 내가 붙을 수 있는 것들 중에 값이 최대인 것에 붙겠다라는 뜻이다.
|
||||
"""
|
||||
43
workbook_7319/silver/11057-s1.py
Normal file
43
workbook_7319/silver/11057-s1.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# 오르막 수
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
dp = [1]*10
|
||||
|
||||
for _ in range(1, n):
|
||||
temp = dp[-1]
|
||||
dp[-1] = sum(dp)
|
||||
for i in range(8, -1, -1):
|
||||
temp2 = dp[i]
|
||||
dp[i] = dp[i+1] - temp
|
||||
temp = temp2
|
||||
|
||||
print(sum(dp)%10007)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분
|
||||
|
||||
시간 복잡도: 10자리의 dp 테이블을 n번만큼 반복하며 업데이트하기 때문에 O(10n)이다.
|
||||
|
||||
해설: 한 자리수 일때는 0~9까지 그냥 10개이다.
|
||||
두 자리수 일때는 0일때 0~9, 1일때 1~9 ... 로 10개부터 1개까지 다 더한 55개이다.
|
||||
세 자리수 일때는 0--일때, 55개, 1--일때, 11부터 99까지이므로 1~9 ... 1~1까지 45개이므로, 두 자리수 기준으로 0~9일때, 1~9일때.. 경우의 수를 가져온다.
|
||||
그렇다는것은 자리수가 늘어날수록 10개의 수 기준으로 합이 정답이 된다는 뜻이다.
|
||||
따라서 dp = [1]*10으로 해놓고, 자리수가 늘어날수록 합을 계속 계산하면 된다.
|
||||
나는 논리 그대로 55에서 10을 빼고, 45에서 9를 빼고.. 순서로 가다보니 dp를 뒤에서부터 채우느라 temp가 2개 등장했지만,
|
||||
사실 이게 앞에서부터 누적합을 계산하는 것이랑 똑같다.
|
||||
|
||||
수식으로 이해해보자면, dp[i][j]를 i자리수의 끝 숫자가 j일때 경우의 수로 생각해보면, dp[i][j] = dp[i-1][0] + dp[i-1][1] + .. + dp[i-1][j]이다.
|
||||
이건 결국 전 행의 누적합을 의미한다. 또한 dp[i][j-1] = dp[i][0] + .. + dp[i][j-1]이므로, dp[i][j] = dp[i][j-1] + dp[i-1][j]가 된다.
|
||||
따라서 1차원으로 만들면 dp[i] = dp[i-1] + dp[i](이전)이 된다.
|
||||
"""
|
||||
39
workbook_7319/silver/1149-s1.py
Normal file
39
workbook_7319/silver/1149-s1.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# RGB 거리
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
dp = [[float('inf') for _ in range(3)] for _ in range(n)]
|
||||
|
||||
dp[0] = lst[0]
|
||||
|
||||
for i in range(1, n):
|
||||
for j in range(3):
|
||||
dp[i][j] = min([dp[i-1][k]+lst[i][j] for k in range(3) if k != j])
|
||||
|
||||
print(min([dp[n-1][j] for j in range(3)]))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 20분
|
||||
|
||||
시간 복잡도: n*3의 dp 테이블을 채워야 하기 때문에 O(n)이다.
|
||||
|
||||
해설: 트리 형식으로 완전탐색을 해야할 것 같지만, 최선의 플레이만 잘 저장해놓으면 많이 배제시키고 할 수 있다.
|
||||
bfs, 완전탐색, 백트래킹 같은 것이 떠오를 때, dp를 생각해보자.
|
||||
현재 줄에서 3가지 중 하나를 볼때, 본인을 제외한 2가지 경우에 대해서 최선이 보장되어 있다면 지금 선택하는 색깔에 대해 최선의 과거를 가져온 것이다.
|
||||
물론 지금의 선택이 최종 최선을 보장하진 않기 때문에 모든 색깔에 대해 모든 줄에서 최선의 선택을 하고, 마지막에는 그 최선들 중에 최선을 고르면 된다.
|
||||
그럼 그리디 아니냐 할 수 있는데, 그리디로 커버할 수 없는 경우까지 커버하는 것이 이 풀이이다.
|
||||
그리디는 계속 그 줄에서 최소를 선택하는 것이지만, 현재 보이는 최소만 선택했을 때 바로 다음에 같은 색깔로 굉장히 작은 숫자가 나오면 최선이 아니게 된다.
|
||||
따라서 각 줄에서 3가지 중 뭘 선택했을 때 최선인지 모르기 때문에 3가지 색깔에 대해 그 전에 왔던 최선의 길을 계속 보장하는 것이다.
|
||||
"""
|
||||
35
workbook_7319/silver/11659-s3.py
Normal file
35
workbook_7319/silver/11659-s3.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# 구간 합 구하기4
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
def input_ints():
|
||||
return map(int, input().rstrip().split())
|
||||
|
||||
def solution():
|
||||
n, m = input_ints()
|
||||
|
||||
lst = [0]+list(input_ints())
|
||||
|
||||
prefix_sum = lst[:]
|
||||
for i in range(1, n+1):
|
||||
prefix_sum[i] = prefix_sum[i-1]+lst[i]
|
||||
|
||||
for _ in range(m):
|
||||
i, j = input_ints()
|
||||
print(prefix_sum[j]-prefix_sum[i-1])
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 9분
|
||||
|
||||
시간 복잡도: 누적합 리스트를 채우는데 O(n)이 걸린다.
|
||||
|
||||
해설: 구간 합을 m번 계산해야하는데, m이 100,000이하이므로 썼던 것을 재활용하지 않으면 시간초과가 날 것 같았다.
|
||||
구간합은 누적합 - 누적합으로 계산할 수 있기 때문에 누적합을 처음에 계산해놓고 진행했다.
|
||||
"""
|
||||
33
workbook_7319/silver/11726-s3.py
Normal file
33
workbook_7319/silver/11726-s3.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# 2xn 타일링
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
MOD = 10007
|
||||
|
||||
dp = [0] * (n+1)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
|
||||
for i in range(2, n+1):
|
||||
dp[i] = (dp[i-1] + dp[i-2])%MOD
|
||||
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 6분
|
||||
|
||||
시간 복잡도: dp 테이블 n개 채우면 O(n)이다.
|
||||
|
||||
해설: 현재 보는 칸이 생겼을 때 1x2를 넣으려면 i-1칸까지 차있는 상태에서 넣으면 되고, 2x1을 넣으려면 i-2칸까지 차있는 상태에서 넣어야 한다.
|
||||
따라서 dp[i-1] + dp[i-2]이다.
|
||||
"""
|
||||
32
workbook_7319/silver/11727-s3.py
Normal file
32
workbook_7319/silver/11727-s3.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# 2×n 타일링 2
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
dp = [0] * (n+1)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
|
||||
for i in range(2, n+1):
|
||||
dp[i] = (dp[i-1]*1) + (dp[i-2]*2)
|
||||
|
||||
print(dp[n]%10007)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 10분
|
||||
|
||||
시간 복잡도: n짜리 테이블을 한번씩만 보면서 채우기 때문에 O(n)이다.
|
||||
|
||||
해설: 과거부터 쌓아온 경우의 수가 현재의 결과에 영향을 미치고, 한 번 결정되면 바뀌지 않기 때문에 dp이다.
|
||||
현재 1칸이 생겼을 때 과거로부터 놓는 경우를 생각해보면 꽉채워진 상태에서 2x1을 놓는 방법 1가지와 한칸 남겨놓고 2x2에서 만들 수 있는 경우의 수 2가지이다.
|
||||
이전까지의 경우의 수에 다음 놓을 수 있는 경우의 수가 1가지라면 dp[i-1]*1이고, 2가지일때는 dp[i-2]*2이다.
|
||||
이 둘을 합친 것이 현재 칸의 경우의 수이다.
|
||||
"""
|
||||
40
workbook_7319/silver/14501-s3.py
Normal file
40
workbook_7319/silver/14501-s3.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 퇴사
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
t_p = [(0, 0)] + [tuple(map(int, input().rstrip().split())) for _ in range(n)] + [(0, 0)]
|
||||
dp = [0] * (n+2)
|
||||
|
||||
for i in range(1, n+2):
|
||||
dp[i] = t_p[i][1]
|
||||
for j in range(i-1, 0, -1):
|
||||
if j+t_p[j][0] > i:
|
||||
continue
|
||||
dp[i] = max(dp[i], dp[j]+t_p[i][1])
|
||||
|
||||
print(dp[n+1])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 29분
|
||||
|
||||
시간 복잡도: 현재 보는 날짜에서 이전 날짜까지를 다 확인해보기 때문에 O(n^2)이다.
|
||||
|
||||
해설: 현재 보는 날짜로 올 수 있는 이전의 날짜들만 확인하고 싶었는데, set이나 dict에 계속 저장해놓고 갱신하는 것도 시간이 들기 때문에
|
||||
그냥 이전 날짜를 다 보고 현재 날짜로 올 수 있는 날짜들만 계산을 했다.
|
||||
|
||||
근데 이걸 dp를 거꾸로 채우면 O(n)으로 가능하다.
|
||||
현재 보는 날짜에 상담 여부를 결정하는데, 전제 조건은 현재 날짜에서 상담을 진행하면 퇴사날짜를 넘기지 않는 것이 조건이다.
|
||||
만약 넘긴다면 그냥 dp[i+1]의 값을 가져와서 오늘은 상담을 안한 것으로 간주한다.
|
||||
만약 퇴사 날짜를 넘기지 않는다면, max(dp[i+1], p[i]+dp[i+t[i]])로
|
||||
오늘 상담을 했을 경우 끝나는 미래 시점의 값에 오늘 상담 값을 더한 것과 그냥 오늘 상담을 안했을 때 값을 비교하여 최대값을 계산한다.
|
||||
"""
|
||||
34
workbook_7319/silver/1463-s3.py
Normal file
34
workbook_7319/silver/1463-s3.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# 1로 만들기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
dp = [float('inf')] * (n+1)
|
||||
|
||||
dp[n] = 0
|
||||
|
||||
for i in range(n-1, 0, -1):
|
||||
way1 = dp[i*3] if i*3 <= n else float('inf')
|
||||
way2 = dp[i*2] if i*2 <= n else float('inf')
|
||||
way3 = dp[i+1] if i+1 <= n else float('inf')
|
||||
dp[i] = min(way1+1, way2+1, way3+1)
|
||||
|
||||
print(dp[1])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 8분
|
||||
|
||||
시간 복잡도: n개의 dp 테이블을 채워야하기 때문에 O(n)이다.
|
||||
|
||||
해설: 현재 보는 수까지 오는 방법을 생각해봤을 때 3가지 방법이 있고, 거기서 최소 값에 +1을 한 것이 현재 보는 수까지 온 최단 경로이다.
|
||||
범위 조건만 잘 설정해서 진행하면 끝
|
||||
"""
|
||||
37
workbook_7319/silver/15988-s2.py
Normal file
37
workbook_7319/silver/15988-s2.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# 1, 2, 3 더하기 3
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
MOD = 1000000009
|
||||
|
||||
dp = [0]*1000001
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
dp[2] = 2
|
||||
|
||||
for i in range(3, 1000001):
|
||||
dp[i] = (dp[i-3] + dp[i-2] + dp[i-1])%MOD
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 6분
|
||||
|
||||
시간 복잡도: dp테이블 n개 다 채우는데 O(n)걸림. 그리고 테스트 케이스에 따라 더 걸리기 때문에 O(n+t)이다.
|
||||
|
||||
해설: 순서가 자유로운 숫자 만들기는 하나씩만 쓸 필요 없이, 여러 방향에서 올 수 있는 경우의 수를 다 고려해서 더하면 된다.
|
||||
이 문제에서 포인트는 숫자가 너무 커서 mod를 써서 dp에 계속 저장해놔야 한다는 것이다.
|
||||
mod 수식의 항등성은 1904번 문제 해설에서 확인하자.
|
||||
"""
|
||||
41
workbook_7319/silver/1904-s3.py
Normal file
41
workbook_7319/silver/1904-s3.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# 01타일
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
mod = 15746
|
||||
|
||||
dp = [0] * (n+1)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
|
||||
for i in range(2, n+1):
|
||||
dp[i] = (dp[i-2]+dp[i-1])%mod
|
||||
|
||||
print(dp[n])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 19분
|
||||
|
||||
시간 복잡도: dp 테이블 채우기는 O(n)이다.
|
||||
|
||||
해설: 현재 보는 칸이 생겼을 때 과거의 어느 시점들에서 올 수 있는지 확인해야 한다. -1번째 칸에서 1 타일만 붙인 경우, -2번째 칸에서 00 타일만 붙인 경우이다.
|
||||
-2번째 칸에서 11을 붙일 수도 있다고 생각할 수 있지만 그건 첫번째 조건에서 고려한 것이다.
|
||||
하다가 좀 헷갈리면 주어진 방법들을 기준으로 그것들이 쓰일 수 있는 고유한 상황만 확인하면 된다. 따라서 두 상황에서 1가지 경우씩 현재로 올 수 있기 때문에
|
||||
dp[i-1]*1 + dp[i-2]*1 이다.
|
||||
근데 여기서 숫자가 너무 커지면 메모리 초과가 발생할 수 있다.(mod 값으로 답하라는 것이 힌트)
|
||||
답을 다 dp에 계산하고 마지막에만 mod를 하는건 의미가 없다.
|
||||
따라서 계산할때마다 mod를 계산해서 그 값을 넣어야 하는데, 그럼 값이 훼손되는게 아닌가 싶다.
|
||||
이때는 mod의 성질을 살펴보면 되는데 (a+b)%m = ((a%m)+(b%m)%m)이다.
|
||||
우리가 구해야하는 값은 dp[a+b]%m인데, dp 테이블에 값을 넣는 식과 비교해보면 dp 값에는 mod를 계산한 결과가 계속 들어가고 있고,
|
||||
그 mod 계산 결과값을 더하고 또 mod를 하기 때문에 이는 ((a%m)+(b%m)%m)과 같다고 할 수 있다.
|
||||
따라서 전혀 지장이 없다.
|
||||
"""
|
||||
55
workbook_7319/silver/1912-s2.py
Normal file
55
workbook_7319/silver/1912-s2.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# 연속합
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = [0]+list(map(int, input().rstrip().split()))
|
||||
|
||||
prefix_sum = [0] * (n+1)
|
||||
min_lst = [0]*(n+1)
|
||||
|
||||
prefix_sum[0] = 0
|
||||
min_lst[0] = 0
|
||||
now_min = 0
|
||||
|
||||
for i in range(1, n+1):
|
||||
prefix_sum[i] = prefix_sum[i-1] + lst[i]
|
||||
min_lst[i] = now_min
|
||||
now_min = min(now_min, prefix_sum[i])
|
||||
|
||||
result = float('-inf')
|
||||
for i in range(1, n+1):
|
||||
result = max(result, prefix_sum[i]-min_lst[i])
|
||||
|
||||
print(result)
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: 모든 계산과 반복은 O(n)에 끝난다.
|
||||
|
||||
해설: 연속된 부분합을 편하게 다루기 위해 prefix_sum을 생각하였다.
|
||||
그 후 prefix_sum들을 살펴보니, 모든 prefix_sum에 대해서 그 앞에 있는 것들 중 제일 작은 prefix_sum 빼면 최대가 나올 것 같았다.
|
||||
그럼 그 구간의 제일 작은 것들을 매번 찾을 수는 없으니, prefix_sum을 계산하면서 제일 작은 것을 기록해야겠다고 생각했다.
|
||||
그렇게 되면 계속 O(n)으로 다 처리할 수 있다.
|
||||
제일 작은 것을 기록하려다보니 계산된 prefix_sum 중에 작은 것을 기록하려고 했는데, 사실 계산된 prefix_sum이 음수가 아닌 이상, 제일 작은 것은 0이 맞다.
|
||||
따라서 계산된 prefix_sum 이전에 0을 넣고, 쭉 계산을 진행했다.
|
||||
마지막 반복문으로 result를 모든 prefix_sum에 대해 그 구간의 최소값을 빼보며 result의 최대값을 구했다.
|
||||
|
||||
이 논리를 좀 더 직관적으로 말하는 풀이법이 있는 kadane라는 것이다.
|
||||
dp[i]를 볼때 i번째 숫자로 새로 시작할지, 기존 최적 수열에 i를 붙일지 선택하는 것이다.
|
||||
lst[i] > dp[i] + lst[i]라는 뜻은 지금까지 최선을 다해온 팀이 있는데, 내가 들어가는 것보다 나 혼자 시작하는게 더 나은 경우이다.
|
||||
lst[i] < dp[i] + lst[i]라는 뜻은 내가 너무 멍청해서 팀원들이 플러스 역할을 해준다는 경우이다.
|
||||
이 나혼자 새로 시작한다는 시점이 바로 내 풀이의 now_min이 바뀌는 시점이다. 너무 벌레를 만나서 그 벌레를 끊고 이후부터 새로 시작했다는 뜻이다.
|
||||
여기서도 result를 계속 max값 업데이트를 해줘야하는데 관계를 끊고 새로 시작했다고 해도, 어떤 팀들은 이미 최고의 플레이를 했을 수도 있기 때문이다.
|
||||
"""
|
||||
39
workbook_7319/silver/1932-s1.py
Normal file
39
workbook_7319/silver/1932-s1.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# 정수 삼각형
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
triangle = [[] for _ in range(n)]
|
||||
|
||||
for i in range(n):
|
||||
triangle[i] = list(map(int, input().rstrip().split()))
|
||||
|
||||
dp = [[0] * i for i in range(1, n+1)]
|
||||
dp[0][0] = triangle[0][0]
|
||||
|
||||
for i in range(1, n):
|
||||
for j in range(len(dp[i])):
|
||||
for k in range(2):
|
||||
if j-k >= len(dp[i-1]) or j-k < 0:
|
||||
continue
|
||||
dp[i][j] = max(dp[i][j], dp[i-1][j-k]+triangle[i][j])
|
||||
|
||||
print(max(dp[n-1]))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 15분
|
||||
|
||||
시간 복잡도: 전체 수에 대해서 진행하기 때문에 O(n^2)이다.
|
||||
|
||||
해설: 1149번(RGB로 집 칠하기) 문제랑 비슷하다. 현재 값을 선택할 때 여기까지 올 수 있는 경우의 수 중 최선의 플레이를 고르고, 마지막에 마지막 라인 중에서
|
||||
최선을 선택하는 방식이다. 1149번에서 설명했지만, 그리디와는 다르게 현재 선택한 수가 최선일지는 모르는 것이기 때문이다.
|
||||
"""
|
||||
45
workbook_7319/silver/2156-s1.py
Normal file
45
workbook_7319/silver/2156-s1.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# 포도주 시식
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = [0] * n
|
||||
for i in range(n):
|
||||
lst[i] = int(input().rstrip())
|
||||
|
||||
dp = [0] * n
|
||||
dp[0] = lst[0]
|
||||
|
||||
if n >= 2:
|
||||
dp[1] = lst[0] + lst[1]
|
||||
|
||||
if n >= 3:
|
||||
dp[2] = max(lst[0]+lst[1], lst[1]+lst[2], lst[0]+lst[2])
|
||||
|
||||
|
||||
for i in range(3, n):
|
||||
dp[i] = max(dp[i-1], dp[i-2]+lst[i], dp[i-3]+lst[i-1]+lst[i])
|
||||
|
||||
|
||||
print(dp[n-1])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 10분
|
||||
|
||||
시간 복잡도: n개의 dp 테이블을 채워야하기 때문에 O(n)이다.
|
||||
|
||||
해설: 2579(계단 오르기) 문제와 비슷하다.
|
||||
다른 점은 1,2칸씩 가는 것이 강제되어 있지 않고, 자유롭게 칸을 왔다갓다 할 수 있다는 것이다.
|
||||
하지만 최대로 마셔야하기 때문에 왔다갔다 할 필요는 없고, 3개가 연속되지 않게 최대한 촘촘하게 먹어야 한다.
|
||||
dp[i]는 i번째 값을 선택할 경우와 선택하지 않을 경우에 따라 max 값을 선택하면 되고, 선택하지 않을 경우 dp[i-1]에서 가져오고,
|
||||
선택할 경우, 바로 앞의 잔을 마셨다면 2번째 잔을 마시지 말았어야하고(dp[i-3]+lst[i-1]+lst[i]),
|
||||
바로 앞의 잔을 안 마셨다면 2번째 전에서 값(dp[i-2]+lst[i])을 가져오면 된다.
|
||||
"""
|
||||
34
workbook_7319/silver/2193-s3.py
Normal file
34
workbook_7319/silver/2193-s3.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# 이친수
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
dp = [0] * (n+1)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
|
||||
for i in range(2, n):
|
||||
dp[i] = dp[i-2]+dp[i-1]
|
||||
|
||||
print(dp[n-1])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 11분
|
||||
|
||||
시간 복잡도: dp 테이블 n개를 채우면 되기 때문에 O(n)이다.
|
||||
|
||||
해설: 현재 칸을 볼 때 0을 넣을 거면 앞이 뭐든 상관없다. 따라서 dp[i-1]을 그대로 가져오면 된다.
|
||||
반면에 1을 넣을 거면 앞이 무조건 0이어야 한다. 따라서 01을 쌍으로 넣어야 하고, 1904번의 문제에서 01과 0 타일로 채우는 것과 같은 문제이다.
|
||||
따라서 두 칸을 통제해야하기 때문에 dp[i-2]개수만큼인 것이다.
|
||||
따라서 dp[i] = dp[i-1] + dp[i-2]이다.
|
||||
현재 칸이 0이거나 1이거나로 완전히 케이스를 분리했기 때문에 중복은 없다.
|
||||
"""
|
||||
40
workbook_7319/silver/2579-s3.py
Normal file
40
workbook_7319/silver/2579-s3.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 계단 오르기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
score = [0] * (n+1)
|
||||
|
||||
for i in range(1, n+1):
|
||||
score[i] = int(input().rstrip())
|
||||
|
||||
dp = [0] * (n+1)
|
||||
dp[1] = score[1]
|
||||
if n >= 2:
|
||||
dp[2] = score[1] + score[2]
|
||||
|
||||
for i in range(3, n+1):
|
||||
dp[i] = max(dp[i-3]+score[i-1]+score[i], dp[i-2]+score[i])
|
||||
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 20분
|
||||
|
||||
시간 복잡도: 각 계단을 한번씩 확인하며 dp를 채우기 때문에 O(n)이다.
|
||||
|
||||
해설: 현재 보는 계단을 오려면 어떻게 올 수 있는지 생각했을 때 방향이 한쪽으로 정해져있다. 무조건 올라오는 것이기 때문에 dp를 쓰면 된다.
|
||||
현재 칸으로 올 수 있는 경우의 수는 2칸 전에서 올라오는 것과 1칸 전에서 올라오되, 그 전에 1칸 점프가 아니어야 한다.(3칸연속 방지)
|
||||
따라서 2번째 경우의 수는 2번째 전 상황까지 강제를 해줘야 한다. 따라서 dp[i-3]+score[i-1]+score[i]가 되는 것이다.
|
||||
또한 i-3을 접근하려면 i가 최소 3부터여야 하기 때문에 dp[1], dp[2]까지는 수동으로 설정해줘야 한다.
|
||||
마지막으로 n은 자연수이므로 1일수도 있다. 이때는 dp[2] 설정이 안되므로 조건문을 달아준다.
|
||||
"""
|
||||
55
workbook_7319/silver/4883-s1.py
Normal file
55
workbook_7319/silver/4883-s1.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# 삼각 그래프
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t = 1
|
||||
while 1:
|
||||
n = int(input().rstrip())
|
||||
if n == 0:
|
||||
break
|
||||
|
||||
g = [[] for _ in range(n)]
|
||||
for i in range(n):
|
||||
g[i] = list(map(int, input().rstrip().split()))
|
||||
|
||||
dp = [[float('inf') for _ in range(3)] for _ in range(n)]
|
||||
|
||||
dp[0][:2] = g[0][:2]
|
||||
dp[0][2] = dp[0][1]+g[0][2]
|
||||
for i in range(1, n):
|
||||
for j in range(3):
|
||||
if i == 1:
|
||||
if j == 0:
|
||||
dp[i][j] = dp[i-1][1]+g[i][j]
|
||||
else:
|
||||
dp[i][j] = min(dp[i][j-1], min(dp[i-1][1:]))+g[i][j]
|
||||
else:
|
||||
if j == 0:
|
||||
dp[i][j] = min(dp[i-1][0], dp[i-1][1])+g[i][j]
|
||||
elif j == 1:
|
||||
dp[i][j] = min(dp[i][0], min(dp[i-1]))+g[i][j]
|
||||
else:
|
||||
dp[i][j] = min(dp[i][1], dp[i-1][j-1], dp[i-1][j])+g[i][j]
|
||||
|
||||
print(f'{t}. {dp[n-1][1]}')
|
||||
t += 1
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: n*3 테이블을 모두 채우는 것이기 때문에 O(3n)이다.
|
||||
|
||||
해설: 1149번(RGB 집 칠하기) 문제처럼 현재 보는 수까지 오는 최적을 계속 계산하면 된다.
|
||||
조금 다른 점은 분기 조건이 다르다는 점인데, 오른쪽, 아래, 오른쪽 아래, 왼쪽 아래, 이렇게 총 4가지 방향으로 이동할 수 있다.
|
||||
또 하나의 고려할 점은 노드 값에 음수도 가능하기 때문에 여러 노드를 거치는 것이 꼭 손해는 아니라는 것이다.
|
||||
따라서 이것에 맞게 최소값을 찾아와야 하고, 1,2,3열에 따라 올 수 있는 곳이 다르기 때문에 잘 지정해서 해야한다.
|
||||
또한 시작인 [0][1]이라는 점에 의해서 0,1 행의 노드들은 특수성이 있기 때문에 이 부분들은 직접 체크하고 반복문을 돌리는 것이 낫다.
|
||||
"""
|
||||
36
workbook_7319/silver/9095-s3.py
Normal file
36
workbook_7319/silver/9095-s3.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# 1,2,3 더하기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
dp = [0] * (11)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
dp[2] = 2
|
||||
|
||||
for i in range(3, 11):
|
||||
dp[i] = dp[i-1]+dp[i-2]+dp[i-3]
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
print(dp[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 20분
|
||||
|
||||
시간 복잡도: n개의 dp 테이블을 한번만 채우면 되기 때문에 O(n)이다.
|
||||
|
||||
해설: 이 문제는 순서가 다른 것은 다르게 보는 순열이다. 따라서 순서를 고정하지 않고, 자유도를 주어서 현재 보는 수로 오기 위해 +1, +2, +3을 한 수들의
|
||||
모든 경우를 다 더하면 된다.
|
||||
반면 순서가 달라도 같은 것으로 보는 조합의 경우에는 순서를 고정시켜줘야 한다. 따라서 1만 썼을 때 경우의 수를 다 계산하고, 2를 썼을 때 경우, 3을 썼을 때 경우,
|
||||
이렇게 나누면 순서가 고정되어 자동으로 조합 계산을 한 것처럼 된다.
|
||||
"""
|
||||
32
workbook_7319/silver/9461-s3.py
Normal file
32
workbook_7319/silver/9461-s3.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# 파도반 수열
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
dp = [0] * 102
|
||||
dp[:5] = [1,1,1,2,2]
|
||||
|
||||
for i in range(5, 102):
|
||||
dp[i] = dp[i-5]+dp[i-1]
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
print(dp[n-1])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 17분
|
||||
|
||||
시간 복잡도: n개의 dp 테이블을 채워야하기 때문에 O(n)이다.
|
||||
|
||||
해설: 나선모양으로 2개의 변을 계속 더하기 때문에 어디 값 2개가 더해지는지 규칙을 파악하면 된다.
|
||||
따라서 dp[i] = dp[i-5]+dp[i-1]인 것을 알 수 있고, 반복문을 위해 dp[4]까지는 구해놔야 dp[5]부터 시작할 수 있다.
|
||||
"""
|
||||
37
workbook_7319/silver/9465-s1.py
Normal file
37
workbook_7319/silver/9465-s1.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# 스티커
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
lst = [list(map(int, input().rstrip().split())) for _ in range(2)]
|
||||
dp = [[0]*n for _ in range(2)]
|
||||
|
||||
dp[0][0] = lst[0][0]
|
||||
dp[1][0] = lst[1][0]
|
||||
|
||||
for i in range(1, n):
|
||||
dp[0][i] = max(dp[0][i-1], dp[1][i-1]+lst[0][i])
|
||||
dp[1][i] = max(dp[1][i-1], dp[0][i-1]+lst[1][i])
|
||||
|
||||
print(max(dp[0][n-1], dp[1][n-1]))
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 20분
|
||||
|
||||
시간 복잡도: 2*n 테이블을 채워야하기 때문에 O(2n)이다.
|
||||
|
||||
해설: 한 열에서 동시에 선택을 할 수는 없으므로, 각 행마다 경우의 수를 구해가야 하고, 한 행이 생길때마다 선택할 수 있는 경우를 보면 된다.
|
||||
하나의 값을 볼때, 이걸 선택한다면 이전 열의 다른 행에서 와야하고, 선택하지 않는다면 이전 열의 같은 행에서 오면 된다.
|
||||
"""
|
||||
54
workbook_8708/gold/1253-g4.py
Normal file
54
workbook_8708/gold/1253-g4.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# 좋다
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def two_pointer(l, r, nums, i, target):
|
||||
while l < r:
|
||||
if l == i:
|
||||
l += 1
|
||||
continue
|
||||
if r == i:
|
||||
r -= 1
|
||||
continue
|
||||
|
||||
now = nums[l] + nums[r]
|
||||
if now == target:
|
||||
return True
|
||||
if now < target:
|
||||
l += 1
|
||||
else:
|
||||
r -= 1
|
||||
return False
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
nums = list(map(int, input().rstrip().split()))
|
||||
|
||||
sorted_nums = sorted(nums)
|
||||
count = 0
|
||||
|
||||
for i in range(n):
|
||||
if two_pointer(0, n-1, sorted_nums, i, sorted_nums[i]):
|
||||
count += 1
|
||||
|
||||
print(count)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: 모든 범위에 대해 투 포인터는 O(n)이고, 모든 숫자가 타겟이 되기 때문에 O(n^2)이다.
|
||||
|
||||
해설: 모든 것을 확인해야 하는 여부를 생각해봤을 때, 어떤 수가 있을지 모르기 때문에 다 봐야한다.
|
||||
그럼 두 개의 조합을 모두 봐야 하나?를 생각했을 때 정렬해서 투 포인터를 쓰면 다 보지 않아도 된다.
|
||||
이제 범위를 본인보다 작은 것들에서 투포인터를 진행하며 구현을 했다.
|
||||
근데 틀렸다. 왜 why? 수가 자연수만 있는 것이 아니었다. 당연히 자연수 범위라고 생각했는데 알고보니 절대값으로 범위가 표현되어 있었다.
|
||||
음수와 양수를 합치면 값이 줄어들기 때문에 타겟 숫자의 오른쪽도 후보가 될 수 있어서 모든 범위에 대해 계속 투포인터를 진행해야 한다.
|
||||
"""
|
||||
80
workbook_8708/gold/12919-g5.py
Normal file
80
workbook_8708/gold/12919-g5.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# A와 B 2
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_same(dq, start, lst_s):
|
||||
if start == -1:
|
||||
dq = list(reversed(dq))
|
||||
for i in range(len(dq)):
|
||||
if dq[i] != lst_s[i]:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
t = input().rstrip()
|
||||
|
||||
lst_s = list(s)
|
||||
dq = deque(list(t))
|
||||
result = []
|
||||
|
||||
def bt(now_dq, start, end):
|
||||
if len(now_dq) == len(lst_s):
|
||||
result.append(check_same(now_dq, start, lst_s))
|
||||
return
|
||||
|
||||
if now_dq[start] == "A":
|
||||
if now_dq[end] == "B":
|
||||
return
|
||||
else:
|
||||
tmp = now_dq.pop() if start == 0 else now_dq.popleft()
|
||||
bt(now_dq, start, end)
|
||||
now_dq.append(tmp) if start == 0 else now_dq.appendleft(tmp)
|
||||
|
||||
elif now_dq[start] == "B":
|
||||
if now_dq[end] == "A":
|
||||
tmp = now_dq.pop() if start == 0 else now_dq.popleft()
|
||||
bt(now_dq, start, end)
|
||||
now_dq.append(tmp) if start == 0 else now_dq.appendleft(tmp)
|
||||
|
||||
start, end = end, start
|
||||
tmp = now_dq.pop() if start == 0 else now_dq.popleft()
|
||||
bt(now_dq, start, end)
|
||||
now_dq.append(tmp) if start == 0 else now_dq.appendleft(tmp)
|
||||
|
||||
start, end = 0, -1
|
||||
bt(dq, start, end)
|
||||
if 1 in result:
|
||||
print(1)
|
||||
else:
|
||||
print(0)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간 20분
|
||||
|
||||
시간 복잡도: deque는 연결 리스트라서 i번째 원소에 접근 시간이 O(n)이다.(충격적인 사실)
|
||||
따라서 check_same이 O(n^2)이 될 수 있고, 이대로 bt까지 해버리면 시간복잡도는 어후... 최대 길이가 50이라 살았다.
|
||||
|
||||
해설: s에서 t를 가려고 하니 2가지 경우의 수를 49번까지 해야하기 때문에 2^49라서 말이 안된다고 생각했다.
|
||||
그래서 t에서 s로 가려고 생각하다보니 시작 끝이 A-A, A-B, B-A, B-B에 따라 경우의 수가 많이 없을 것 같다고 생각했다.
|
||||
각각 현재 상황에 올 수 있는 이전 상황을 세팅해보면,
|
||||
A-A: 맨 앞이 A였고, A를 붙임(경우 1)
|
||||
A-B: 있을 수 없는 상황(B를 붙이면 뒤집어야하기 때문 -> 경우 0)
|
||||
B-B: 맨 앞이 B였고, B를 붙임(경우 1)
|
||||
B-A: 맨 앞 A였고 B를 붙임 or 맨 앞 B였고, A를 붙임(경우 2)
|
||||
처음에는 B-A도 경우가 1인줄 알고 단순 구현으로 해봤는데 틀렸다.
|
||||
알고보니 B-A에서 경우가 2가지였고, 이때부터 백트래킹을 고민하였다.
|
||||
4가지 상황에 대해 각각 분기해서 bt를 진행하였고, 슬라이싱으로 넘기는 것은 시간복잡도가 자른만큼 생기기 때문에 deque를 이용해서
|
||||
빼고 bt하고 다시 뺐던거 넣는 방식으로 기존 dq를 유지하면서 bt를 진행했다.
|
||||
근데 각 상황에 대해 분기처리를 하면 코드 중복이 좀 많이 발생하여 4가지 상황을 자세히 살펴보니
|
||||
끝이 A일때 pop으로 bt 진행하고, 시작이 B일때 popleft로 bt 진행하면 그냥 모든 조건을 맞출 수 있었다.
|
||||
"""
|
||||
57
workbook_8708/gold/13549-g5.py
Normal file
57
workbook_8708/gold/13549-g5.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 숨바꼭질 3
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
MAX_LINE = 100000
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
|
||||
move = [1, -1]
|
||||
visited = [float('inf')] * (MAX_LINE+1)
|
||||
dq = deque([n])
|
||||
visited[n] = 0
|
||||
|
||||
while dq:
|
||||
now = dq.popleft()
|
||||
|
||||
if now == k:
|
||||
break
|
||||
|
||||
teleport = now*2
|
||||
while 0 <= teleport <= MAX_LINE and visited[teleport] > visited[now]:
|
||||
dq.append(teleport)
|
||||
visited[teleport] = visited[now]
|
||||
teleport = teleport*2
|
||||
|
||||
for m in move:
|
||||
moved = now+m
|
||||
if 0 <= moved <= MAX_LINE and visited[moved] > visited[now]+1:
|
||||
dq.append(moved)
|
||||
visited[moved] = visited[now]+1
|
||||
|
||||
print(visited[k])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 39분
|
||||
|
||||
시간 복잡도: 한 노드를 pop했을 때 많아도 log(100000)정도이기 때문에 n=100000일때 O(nlogn)정도이다.
|
||||
|
||||
해설: 뱀과 사다리(16928)랑 비슷한 문제인 것 같다. 현재 위치에서 순간이동하는 곳은 같은 시간으로 넣어야 하고, 그 곳을 visited를
|
||||
만드는 방식으로 진행하는 것이었다. 하지만 이 문제는 순간이동 위치가 1:1 대응이 아니고, 뒤로 순간이동 하는 것은 없다는 점에서 차이가 있다.
|
||||
하지만 일단 중요한 건 bfs 레벨에서 순간이동에 대응되는 위치들이 다 같은 레벨이기 때문에 얘네를 큐에 순서대로 잘 넣는 것이다.
|
||||
그렇게 했는데 99퍼센트에서 틀렸다고 나왔다.
|
||||
생각해보니까 앞뒤로 이동해서 이미 방문해버린 것을 같은 턴에 순간이동으로 올 수 있었다면 더 나은 방법으로 올 수 있음.
|
||||
예를 들어 4 6의 경우 4 8 16 .. 5 3 일때 5에서 6을 +1로 방문했는데, 사실 3에서 6으로 순간이동하면 +1 없이 갈 수 있다.
|
||||
결국에는 또 같은 레벨의 구분을 제대로 하지 못했다.
|
||||
일단 대안으로는 레벨 조정이 있겠지만 그냥 방문 기준으로 노드를 넣지 말고, 다 계산해봐서 지금 값보다 더 좋은 방향이 있다면 큐에 다시 추가하도록
|
||||
조정하였다.
|
||||
"""
|
||||
57
workbook_8708/gold/14719-g5.py
Normal file
57
workbook_8708/gold/14719-g5.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 빗물
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
h, w = map(int, input().rstrip().split())
|
||||
|
||||
blocks = map(int, input().rstrip().split())
|
||||
|
||||
stack = []
|
||||
result = 0
|
||||
for b in blocks:
|
||||
if stack:
|
||||
if b < stack[0]:
|
||||
stack.append(b)
|
||||
continue
|
||||
else:
|
||||
while stack:
|
||||
if len(stack) == 1:
|
||||
stack.pop()
|
||||
break
|
||||
result += stack[0] - stack.pop()
|
||||
stack.append(b)
|
||||
else:
|
||||
stack.append(b)
|
||||
|
||||
while stack:
|
||||
if len(stack) == 1:
|
||||
stack.pop()
|
||||
break
|
||||
now = stack.pop()
|
||||
while stack and stack[-1] <= now:
|
||||
result += now - stack.pop()
|
||||
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분
|
||||
|
||||
시간 복잡도: 모든 블럭이 stack에 한번씩 들어갔다가 나오기 때문에 O(n)이다.
|
||||
|
||||
해설: 이전에 풀었던 지붕 쌓기와 비슷한 문제이다. 이런 문제들에서 시간을 뺐기지 않고 가려면 좀 공식화해둘 필요가 있다.
|
||||
내가 기억해야하고 기억하지 않아도 될 것들을 구분해야 하는데,
|
||||
(1) 시작 블럭의 높이를 기준으로 동등하거나 그 이상의 블럭이 나오면 지금까지 나왔던 것들은 시작 블럭 기준으로 계산하고, 잊어도 됨
|
||||
1번을 진행하면서 stack의 내용물은 pop되고 새로운 시작 기준점이 잡힌다.
|
||||
(2) 시작 블럭의 높이를 기준으로 미만인 것들만 있다면 pop될 일이 없기 때문에 다 끝나면 stack에 내용물이 있을 것이다.
|
||||
이제 stack을 다 비우면서 모든 블럭에 대한 계산을 진행해야 한다.
|
||||
이때부터는 1번의 역순이다. 왜 why? 시작 블럭 기준으로 미만인 것들만 있었다는 것은 오르내리막이 있어도 최종적으로는 내리막이었다는 뜻이고,
|
||||
이는 거꾸로 보면 1번에서 하던것처럼 동등하거나 그 이상의 블럭이 무조건 있다는 뜻이다.
|
||||
따라서 기준점을 stack[-1]로 잡고 1번 방식을 진행하면 된다.
|
||||
"""
|
||||
48
workbook_8708/gold/15989-g5.py
Normal file
48
workbook_8708/gold/15989-g5.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# 1, 2, 3 더하기 4
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def update_dp(start, n, dp):
|
||||
for i in range(start, n+1):
|
||||
dp[i] = (sum(dp[i-1]), sum(dp[i-2][1:]), sum(dp[i-3][2:]))
|
||||
|
||||
return
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
dp = [-1] * 10001
|
||||
dp[1], dp[2], dp[3] = (1, 0, 0), (1, 1, 0), (2, 0, 1)
|
||||
start = 4
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
if dp[n] == -1:
|
||||
update_dp(start, n, dp)
|
||||
start = n+1
|
||||
print(sum(dp[n]))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간
|
||||
|
||||
시간 복잡도: dp[n]까지 채우는데 한번 채울때 O(1)이므로 테스트케이스 중에 가장 큰 n만큼 시간이 걸린다. O(max(n))
|
||||
|
||||
해설: 몇 가지 n에 대해 모든 경우의 수를 만들어보니,
|
||||
dp[n]을 구할 때 이전 숫자들의 경우에다 1, 2, 3 을 더해서 할 수 있겠다고 생각했다.
|
||||
n-1, n-2, n-3에서 1, 2, 3의 숫자를 더해서 만들고, 중복되는 것들을 없애기 위해 규칙을 파악했다.
|
||||
1 > 2 > 3 으로 우선순위를 두고, 각각 포함된 것들의 개수를 기록해나간다.
|
||||
1 0 0, 1 1 0, 2 0 1, 3 1 0, 4 1 0, 5 1 1 ... 이 다음 것을 찾아보자
|
||||
n-1에서 모든 경우에 1을 더해주면 되기 때문에 5+1+1 = 7이 된다.
|
||||
n-2에서 모든 경우에 1을 추가한 것이 이미 n-1에 있다. 따라서 1을 안 쓴 2, 3 그룹의 경우에만 2를 더해주면 되기 때문에 1+0=1이 된다.
|
||||
n-3도 n-2 원리를 적용하여 3 그룹의 경우에만 3을 더해주면 0=0이 된다.
|
||||
따라서 7 1 0 이되고, 숫자 7의 전체 경우의 수는 8개이다.
|
||||
근데 이렇게 안하고 더 쉬운 방법이 있다.
|
||||
1만 쓴 경우, 2도 쓴 경우, 3도 쓴 경우로 도구를 늘려가면서 dp를 갱신하는 방법이다.
|
||||
1만 쓴 경우는 당연히 다 1이다.
|
||||
2를 추가하게 되면 dp[i] += dp[i-2]로 현재 숫자-2에서 나온 모든 경우의 수의 끝에 +2를 붙이는 것이다. 3도 마찬가지.
|
||||
"""
|
||||
87
workbook_8708/gold/16928-g5.py
Normal file
87
workbook_8708/gold/16928-g5.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# 뱀과 사다리 게임
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
g = [-1] * 101
|
||||
visited = [-1] * 101
|
||||
for _ in range(n+m):
|
||||
v, w = map(int, input().rstrip().split())
|
||||
g[v] = w
|
||||
|
||||
q = deque([1])
|
||||
visited[1] = 0
|
||||
while q:
|
||||
now = q.popleft()
|
||||
for k in range(1, 7):
|
||||
nxt = now+k
|
||||
if nxt > 100:
|
||||
continue
|
||||
|
||||
if g[nxt] != -1:
|
||||
nxt = g[nxt]
|
||||
|
||||
if visited[nxt] == -1:
|
||||
q.append(nxt)
|
||||
visited[nxt] = visited[now]+1
|
||||
|
||||
print(visited[100])
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 몰라
|
||||
|
||||
시간 복잡도: 각 칸당 한번씩만 방문하기 때문에 O(100)이다.
|
||||
|
||||
해설: 1697-s1과 같은 실수를 반복했다. 앞 뒤로 갈 수 있는 것은 dp로 할때 어디부터 채워야할지 모르기 때문에 bfs로 해야했거늘..
|
||||
현재 칸에서 주사위를 굴려서 6칸을 다 갈 수 있고, 이때 사다리나 뱀이 있으면 그곳으로 바로 이동해야 한다.
|
||||
근데 나는 일단 6칸을 다 방문처리하고, now에서 사다리나 뱀이 있으면 방문하는 방식으로 진행을 했다.
|
||||
하지만 이렇게 하면 사다리를 타고 올라가는 곳이 레벨이 1이라고 할때, 주사위로 가서 한 번 더 간 칸, 즉 레벨 2의 칸이 큐에 먼저 들어간다.
|
||||
레벨이 꼬여버리기 때문에 주사위로 온 칸이 사다리가 연결되어 있다면 바로 이동해서 그 칸을 큐에 넣는 것이 순서가 맞다.
|
||||
주사위로 나온 칸은 그럼 계속 방문처리가 안되는 것 아니냐라고 생각할 수 있지만, 실제로 방문처리가 안되기도 하고
|
||||
그 칸은 항상 사다리로 이동한 칸과 같은 취급을 받기 때문에 상관없다.
|
||||
이렇게 최단거리 문제를 bfs로 풀때는 레벨을 잘 따져야 할 것 같다.
|
||||
"""
|
||||
|
||||
# def dp_up(dp, g): # 30분
|
||||
# for i in range(2, 7):
|
||||
# for j in range(i-1, 0, -1):
|
||||
# dp[i] = min(dp[i], dp[j]+1)
|
||||
# dp[i] = min(dp[i], dp[g[i]] if g[i] != -1 else float('inf'))
|
||||
|
||||
|
||||
# for i in range(7, 101):
|
||||
# dp[i] = min(dp[i-1]+1, dp[i-2]+1, dp[i-3]+1, dp[i-4]+1, dp[i-5]+1, dp[i-6]+1, dp[g[i]] if g[i] != -1 else float('inf'))
|
||||
|
||||
# return
|
||||
|
||||
# def dp_down(dp, g):
|
||||
# for i in range(100, 1, -1):
|
||||
# dp[i] = min(dp[i-1]+1, dp[i-2]+1, dp[i-3]+1, dp[i-4]+1, dp[i-5]+1, dp[i-6]+1, dp[g[i]] if g[i] != -1 else float('inf'))
|
||||
|
||||
# return
|
||||
|
||||
# def solution():
|
||||
# n, m = map(int, input().rstrip().split())
|
||||
# g = [-1] * 101
|
||||
# dp = [float('inf')] * 101
|
||||
# dp[1] = 0
|
||||
|
||||
# for _ in range(n+m):
|
||||
# v, w = map(int, input().rstrip().split())
|
||||
# g[w] = v # 도착점이 key, 시작점이 value
|
||||
|
||||
# dp_up(dp, g)
|
||||
# dp_down(dp, g)
|
||||
# dp_up(dp, g)
|
||||
# print(dp[100])
|
||||
# # print(dp)
|
||||
# # print("70:", dp[70], "72:", dp[72], "67:", dp[67], "68:", dp[68], "98:", dp[98])
|
||||
|
||||
# solution()
|
||||
47
workbook_8708/gold/1806-g4.py
Normal file
47
workbook_8708/gold/1806-g4.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# 부분합
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, s = map(int, input().rstrip().split())
|
||||
|
||||
lst = list(map(int, input().rstrip().split()))
|
||||
|
||||
l, r = 0, 0
|
||||
now = lst[0]
|
||||
result = 100001
|
||||
while l <= r:
|
||||
if now >= s:
|
||||
while now >= s:
|
||||
now -= lst[l]
|
||||
l += 1
|
||||
result = min(result, r-(l-1)+1)
|
||||
|
||||
if r >= n-1:
|
||||
break
|
||||
if now < s:
|
||||
r += 1
|
||||
now += lst[r]
|
||||
|
||||
if result > 100000:
|
||||
result = 0
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 18분
|
||||
|
||||
시간 복잡도: 두 포인터가 모든 원소를 가르키는 것이 최악이므로 O(n)이다.
|
||||
|
||||
해설: 투 포인터를 활용하여 오른쪽으로 값을 추가하고, 왼쪽으로 값을 제외한다.
|
||||
현재 값이 s보다 크면, s보다 값이 작아질때까지 왼쪽 포인터를 오른쪽으로 옮기면서 값을 뺀다.
|
||||
현재 값이 s보다 작으면 오른쪽 포인터를 오른쪽으로 옮기면서 값을 더한다.
|
||||
마지막까지 result 값이 100000보다 크면 답이 없는 것이므로 result를 0으로 만든다.
|
||||
"""
|
||||
51
workbook_8708/gold/1976-g4.py
Normal file
51
workbook_8708/gold/1976-g4.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# 여행가자
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
m = int(input().rstrip())
|
||||
|
||||
g = {}
|
||||
for i in range(n):
|
||||
info = list(map(int, input().rstrip().split()))
|
||||
g[i+1] = [idx+1 for idx, con in enumerate(info) if con == 1]
|
||||
|
||||
plan = list(map(int, input().rstrip().split()))
|
||||
visited = [0] * (n+1)
|
||||
q = deque([plan[0]])
|
||||
visited[plan[0]] = 1
|
||||
while q:
|
||||
now = q.popleft()
|
||||
for city in g[now]:
|
||||
if visited[city]:
|
||||
continue
|
||||
q.append(city)
|
||||
visited[city] = 1
|
||||
|
||||
for city in plan:
|
||||
if visited[city] == 0:
|
||||
print("NO")
|
||||
break
|
||||
else:
|
||||
print("YES")
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 17분
|
||||
|
||||
시간 복잡도: 한 노드당 큐에 한번만 들어오고 나가기 때문에 O(n)인데, 문제는 시작할 때 각 노드마다 연결된 데이터를 읽는 것이
|
||||
O(n^2)이다.
|
||||
|
||||
해설: 뭐가 됐든 시작 도시를 기준으로 하나의 그룹으로 묶여 있으면 된다. 즉 bfs를 진행해서 한 묶음에만 있으면 된다.
|
||||
다른 풀이로 union-find도 있다.
|
||||
공통 조상으로 묶는 방식인데, find 함수는 parent 리스트에서 본인이 parent가 아니면 계속 재귀로 최초 조상을 찾는 것이다.
|
||||
union은 두 노드의 최초 조상을 찾아서 다르면 한쪽으로 편입 시키는 방식이다. 근데 이것도 O(n^2)이다.
|
||||
"""
|
||||
58
workbook_8708/gold/1987-g4.py
Normal file
58
workbook_8708/gold/1987-g4.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# 알파벳
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def solution():
|
||||
r, c = map(int, input().rstrip().split())
|
||||
|
||||
grid = [[1 << (ord(ch)-65) for ch in input().rstrip()] for _ in range(r)]
|
||||
|
||||
dr = [1, -1, 0, 0]
|
||||
dc = [0, 0, 1, -1]
|
||||
|
||||
result = 0
|
||||
|
||||
def dfs(now_r, now_c, mask, depth):
|
||||
is_last = True
|
||||
|
||||
for i in range(4):
|
||||
nxt_r, nxt_c = now_r + dr[i], now_c + dc[i]
|
||||
if 0 <= nxt_r < r and 0 <= nxt_c < c:
|
||||
now_bit = grid[nxt_r][nxt_c]
|
||||
if mask & now_bit:
|
||||
continue
|
||||
dfs(nxt_r, nxt_c, mask | now_bit, depth+1)
|
||||
is_last = False
|
||||
|
||||
if is_last:
|
||||
nonlocal result
|
||||
result = max(result, depth)
|
||||
|
||||
return
|
||||
|
||||
dfs(0, 0, grid[0][0], 1)
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간
|
||||
|
||||
시간 복잡도: 최대로 멀리 갈 수 있는게 알파벳 개수인 26개에 매번 경우의 수는 4이므로 O(4^26)이지만
|
||||
방문한 것들은 안가고 그러면 저것보다는 작을 것 같다.
|
||||
|
||||
해설: 처음에는 아무생각 없이 bfs로 진행했다가 갈 수 있는 거리의 최대치를 생각해보니까 dfs로 다 봐야할 것 같았다.
|
||||
visited는 set으로 관리하면서 copy를 해서 넘겨주는 식으로 재귀 dfs를 했는데(사실상 백트래킹이지..) 시간초과가 났다.
|
||||
생각해보니 계속 copy를 하면 시간이 너무 걸릴 것 같아서 백트래킹 정석대로 dfs 전에 add, 후에 remove 하는 방식으로 했다.
|
||||
질문 게시판을 보면 이렇게 하면 다 풀린다던데 네트워크가 느려서일 것 같았다.
|
||||
일단 더 빠른 방법을 알아봤는데 비트마스크로 하면 더 빠르다고 한다.
|
||||
그래서 비트마스크로 진행을 했고, 이때는 숫자를 넘겨주는 것이니까 복원 과정 필요 없이 업데이트된 숫자만 넘겨주면 된다.
|
||||
근데 이렇게 해도 시간초과가 걸려서 네트워크 문제가 너무 심하다고 생각하며 끝냈다.
|
||||
앞으로도 순서가 명확하고 사용 유무 같은 것을 기록할 일 있으면 비트마스크를 쓰면 좋을 것 같다. 물론 크기도 작은게 낫겠다.
|
||||
"""
|
||||
75
workbook_8708/gold/20055-g5.py
Normal file
75
workbook_8708/gold/20055-g5.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# 컨베이어 벨트 위의 로봇
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
health = [-1] + list(map(int, input().rstrip().split()))
|
||||
robot = [0] * (2*n+1)
|
||||
robot_order = deque([])
|
||||
front = deque([i+1 for i in range(n)])
|
||||
back = deque([i for i in range(2*n, n, -1)])
|
||||
unhealth_count = 0
|
||||
result = 0
|
||||
|
||||
while unhealth_count < k:
|
||||
result += 1
|
||||
front.appendleft(back.popleft())
|
||||
back.append(front.pop())
|
||||
|
||||
if robot[front[-1]] == 1:
|
||||
robot_order.popleft()
|
||||
robot[front[-1]] = 0
|
||||
|
||||
now_robot_len = len(robot_order)
|
||||
for _ in range(now_robot_len):
|
||||
idx = robot_order.popleft()
|
||||
nxt = idx + 1
|
||||
if idx == (2*n):
|
||||
nxt = 1
|
||||
if robot[nxt] == 0 and health[nxt] > 0:
|
||||
robot[idx] = 0
|
||||
robot[nxt] = 1
|
||||
robot_order.append(nxt)
|
||||
health[nxt] -= 1
|
||||
if health[nxt] == 0:
|
||||
unhealth_count += 1
|
||||
else:
|
||||
robot_order.append(idx)
|
||||
|
||||
if robot[front[-1]] == 1:
|
||||
robot_order.popleft()
|
||||
robot[front[-1]] = 0
|
||||
|
||||
if robot[front[0]] == 0 and health[front[0]] > 0:
|
||||
robot_order.append(front[0])
|
||||
robot[front[0]] = 1
|
||||
health[front[0]] -= 1
|
||||
if health[front[0]] == 0:
|
||||
unhealth_count += 1
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 26분
|
||||
|
||||
시간 복잡도: 내구도가 1000까지이고, 이게 다 깎인 것이 k개가 될때까지이므로 O(1000*k)인데, 중간에 로봇이 한칸씩 움직이기 때문에
|
||||
컨베이어벨트 윗부분인 n만큼 for문을 돈다. 근데 나는 로봇이 있는 칸만 확인하기 때문에 O(1000*k*n)보다는 적다.
|
||||
|
||||
해설: 문제조건대로 그대로 구현하면 된다. 벨트가 도는 것은 2개의 deque를 활용해서 구현하였고, 로봇이 있는 칸만 확인하기 위해 robot이 들어간 순서를
|
||||
기록해놓는 robot_order를 queue로 구현한다. 각 단계를 구현하는 것은 기록할 것들만 잘 생각해서 빼먹지 않으면 어렵지 않게 가능하다.
|
||||
또한 2n에서 다음 칸이 1이기 때문에 이것만 예외처리 하면 된다.
|
||||
|
||||
로봇을 올릴 경우 로봇을 내릴 경우
|
||||
robot: 로봇 유무 | 1 | 0
|
||||
health: 내구도 | -1 | -
|
||||
robot_order: 로봇 올린 순서 | append(nxt) | popleft(now)
|
||||
"""
|
||||
48
workbook_8708/gold/20437-g5.py
Normal file
48
workbook_8708/gold/20437-g5.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# 문자열 게임 2
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def find_str(w, k):
|
||||
result = {chr(i): [] for i in range(97, 123)}
|
||||
ans1 = float("inf")
|
||||
ans2 = -1
|
||||
for i, c in enumerate(w):
|
||||
result[c].append(i)
|
||||
|
||||
for lst in result.values():
|
||||
for i in range(len(lst)-k+1):
|
||||
ans1 = min(ans1, lst[i+k-1] - lst[i]+1)
|
||||
ans2 = max(ans2, lst[i+k-1] - lst[i]+1)
|
||||
|
||||
return (ans1, ans2)
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
for _ in range(t):
|
||||
w = input().rstrip()
|
||||
k = int(input().rstrip())
|
||||
|
||||
answer1, answer2 = find_str(w, k)
|
||||
if answer2 == -1:
|
||||
print(answer2)
|
||||
else:
|
||||
print(answer1, answer2)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간 좀 넘게
|
||||
|
||||
시간 복잡도: 각 문자마다 슬라이딩 윈도우로 한번씩만 보기 때문에 O(n)이다.
|
||||
|
||||
해설: 전체 문자열을 한 번만 돌면서 문자마다 시작, 끝 인덱스와 개수 등을 저장하면서 진행하려고 했는데 한번에 하기에는
|
||||
변하는 것이 너무 많아서 문자마다 인덱스를 저장하고 답을 구하기로 했다.
|
||||
이렇게 해도 각 문자마다 한번씩만 보기 때문에 O(n)으로 괜찮다.
|
||||
모든 알파벳에 대해 나오는 인덱스를 리스트에 순서대로 넣은 후 슬라이딩 윈도우로 K만큼에 있는 인덱스들의 차 + 1을 구한다.
|
||||
이것이 문자열의 길이인데 3번은 최소값, 4번은 최대값을 구하면 된다.
|
||||
"""
|
||||
59
workbook_8708/gold/2179-g3.py
Normal file
59
workbook_8708/gold/2179-g3.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# 비슷한 단어
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
now = {"": [(input().rstrip(), i) for i in range(n)]}
|
||||
temp = {}
|
||||
idx = 0
|
||||
while 1:
|
||||
if not now:
|
||||
lst = list(temp.values())
|
||||
print(lst[0][0][0])
|
||||
print(lst[0][1][0])
|
||||
break
|
||||
|
||||
temp = now.copy()
|
||||
now = {}
|
||||
for key in temp:
|
||||
for word, num in temp[key]:
|
||||
if idx >= len(word):
|
||||
continue
|
||||
chr = key+word[idx]
|
||||
if now.get(chr, 0):
|
||||
now[chr].append((word, num))
|
||||
else:
|
||||
now[chr] = [(word, num)]
|
||||
|
||||
for key in list(now.keys()):
|
||||
if len(now[key]) == 1:
|
||||
del now[key]
|
||||
idx += 1
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 오래 걸림
|
||||
|
||||
시간 복잡도: 모든 글자의 글자수를 보기 때문에 최대 글자수를 m이라고 하면 O(nm)이다. 근데 새로운 키를 만들 때 더하기를 하기 때문애 (O(nm*m))이다.
|
||||
|
||||
해설: 모든 단어들을 한글자씩 보면서 딕셔너리에 그 값을 키로 넣는다. 같은 글씨는 같은 키에 리스트로 모은다.
|
||||
두번째 이상의 글자를 볼때는 이전에 있던 키에 현재 글자를 더한 것을 키로 만들어서 반복한다.
|
||||
글자수가 다 다르기 때문에 현재 봐야하는 idx보다 글자 길이가 작으면 그냥 그 글자는 넘어간다.
|
||||
그 후 각 키에 대해 모인 것들의 개수가 1이면 겹치는 녀석이 없는 것이기 때문에 키를 del 한다.
|
||||
이때 del을 한 후 남은 것이 아무것도 없다면 그 녀석들이 최종 상태였으므로 그 녀석들을 가지고 와서 답을 낸다.
|
||||
그 녀석들은 temp에 분해하기 전에 기록해놓는다.
|
||||
계속 입력된 순서대로 꺼내서 진행했기 때문에 temp에 남은 첫 번째 리스트의 1,2번들이 답이다.
|
||||
|
||||
다른 방법으로 사전순으로 정렬하면 어느정도 prefix가 비슷한 애들끼리 모이기 때문에 인접한 것들끼리만 비교해서 최대 길이를 찾고,
|
||||
그 길이만큼 prefix인 녀석들을 모아서 입력 순서가 가장 빠른 녀석 두 놈을 골라서 주면 된다.
|
||||
정렬할 때 O(nlogn)에 글자수만큼 읽어야 되니까, 결국 정렬이 O(mnlogn)만큼 걸리고, 나머지 인접한 것 비교와 답 찾기는 O(nm)이면 된다.
|
||||
따라서 전체는 O(mnlogn)
|
||||
"""
|
||||
74
workbook_8708/gold/22251-g5.py
Normal file
74
workbook_8708/gold/22251-g5.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# 빌런 호석
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_change_table(change_table, now_floor, target_floor):
|
||||
count = 0
|
||||
for i in range(len(now_floor)):
|
||||
count += change_table[int(now_floor[i])][int(target_floor[i])]
|
||||
|
||||
return count
|
||||
|
||||
def count_diff(led1, led2):
|
||||
count = 0
|
||||
for i in range(len(led1)):
|
||||
if led1[i] != led2[i]:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def fill_change_table(change_table, led):
|
||||
for i in range(10):
|
||||
for j in range(10):
|
||||
if i == j:
|
||||
continue
|
||||
if change_table[i][j] != 0:
|
||||
continue
|
||||
change_table[i][j] = count_diff(led[i], led[j])
|
||||
return
|
||||
|
||||
def solution():
|
||||
led = [[0]*7 for _ in range(10)]
|
||||
led[0] = [1, 1, 1, 0, 1, 1, 1]
|
||||
led[1] = [0, 0, 1, 0, 0, 1, 0]
|
||||
led[2] = [1, 0, 1, 1, 1, 0, 1]
|
||||
led[3] = [1, 0, 1, 1, 0, 1, 1]
|
||||
led[4] = [0, 1, 1, 1, 0, 1, 0]
|
||||
led[5] = [1, 1, 0, 1, 0, 1, 1]
|
||||
led[6] = [1, 1, 0, 1, 1, 1, 1]
|
||||
led[7] = [1, 0, 1, 0, 0, 1, 0]
|
||||
led[8] = [1, 1, 1, 1, 1, 1, 1]
|
||||
led[9] = [1, 1, 1, 1, 0, 1, 1]
|
||||
|
||||
change_table = [[0]*10 for _ in range(10)]
|
||||
fill_change_table(change_table, led)
|
||||
|
||||
n, k, p, x = map(int, input().rstrip().split())
|
||||
|
||||
result = 0
|
||||
now_floor = "0"*(k-len(str(x))) + str(x)
|
||||
|
||||
for i in range(1, n+1):
|
||||
if i == x:
|
||||
continue
|
||||
target_floor = "0"*(k-len(str(i))) + str(i)
|
||||
if check_change_table(change_table, now_floor, target_floor) <= p:
|
||||
result += 1
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 46분
|
||||
|
||||
시간 복잡도: 필요한 반전 횟수를 기록한 테이블을 만드는데 상수시간이다.
|
||||
모든 층에 대해 반전횟수 테이블을 참조하여 계산해보기 때문에 O(n)이다.
|
||||
|
||||
해설: led가 켜진 곳은 1, 꺼진 곳은 0으로 해서 두 수를 비교했을 때 다른 숫자인 곳이 필요한 반전 횟수이다.
|
||||
반전횟수 테이블을 가지고 현재 층에서 모든 층을 타겟으로 p보다 반전 횟수가 적은 것의 개수가 답이다.
|
||||
"""
|
||||
50
workbook_8708/gold/2467-g5.py
Normal file
50
workbook_8708/gold/2467-g5.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# 용액
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
lst = list(map(int, input().rstrip().split()))
|
||||
|
||||
result = float('inf')
|
||||
answer = -1
|
||||
l, r = 0, len(lst)-1
|
||||
while l < r:
|
||||
now = lst[l] + lst[r]
|
||||
if abs(now) < result:
|
||||
result = abs(now)
|
||||
answer = (lst[l], lst[r])
|
||||
result = min(result, abs(now))
|
||||
if now == 0:
|
||||
break
|
||||
|
||||
if now > 0:
|
||||
r -= 1
|
||||
else:
|
||||
l += 1
|
||||
|
||||
print(*answer)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 33분
|
||||
|
||||
시간 복잡도: 모든 수를 한번씩 보기 때문에 O(n)이다.
|
||||
|
||||
해설: 모든 경우의 수를 확인해보는 것은 너무 많기 때문에 적절히 줄여서 볼 것만 확인해야 한다.
|
||||
그 생각을 하게 되면 슬라이딩 윈도우와 투 포인터를 떠올릴 수 있다.
|
||||
그 다음 두 가지 포인터를 어떤 상황에서 뭘 움직일지를 정하면 되는데, 0, 1에서 오른쪽으로 출발한다고 하면
|
||||
리스트가 오름차순이기 때문에 어떨때 뭘 옮겨야할지 애매해진다.
|
||||
따라서 0, n-1에서 시작하면 l포인터는 오른쪽으로 가면 숫자가 커지고, r포인터는 왼쪽으로 가면 숫자가 작아지기 때문에
|
||||
0보다 클 경우 숫자를 줄여야되니까 r포인터를 움직이고, 반대의 경우 l포인터를 움직이도록 설정하면 된다.
|
||||
-100 -2 -1 103의 경우에서 처음이 -100 103으로 3이고, 양수이므로 r을 왼쪽으로 움직여서 -100과 -1로 -101을 만든다.
|
||||
이때 -2와 103은 평생 볼일이 없는데 당연하게도 3보다 커질 것이 자명하므로 안 봐도 된다.
|
||||
모든 a[i]에 대해서 이분탐색을 통해 -a[i]와 가장 가까운 수를 찾는 방식으로도 해결할 수 있다. -> 이건 O(nlogn)
|
||||
"""
|
||||
33
workbook_8708/gold/2493-g5.py
Normal file
33
workbook_8708/gold/2493-g5.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# 탑
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
tops = list(map(int, input().rstrip().split()))
|
||||
s = []
|
||||
result = [0] * n
|
||||
for i in range(n-1, -1, -1):
|
||||
while s and tops[i] >= s[-1][1]:
|
||||
idx, _ = s.pop()
|
||||
result[idx] = i+1
|
||||
s.append((i, tops[i]))
|
||||
|
||||
print(*result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 17분
|
||||
|
||||
시간 복잡도: 한 탑당 한번씩 stack에 들어가고 나오기 때문에 O(n)이다.
|
||||
|
||||
해설: 왼쪽부터 확인하면서 stack에 넣고, stack 있는 것들이 현재 보는 것보다 작은 것은 다 빼면
|
||||
그게 stack 있는 애들한테 처음으로 만나는 가장 크거나 같은 탑이다. 그리고 그 탑이 신호를 수신한다는 뜻이다.
|
||||
stack에 남아있는 애들은 본인보다 큰 것을 보지 못한 애들이기 때문에 기존 초기화에서 했던 0으로 냅두면 된다.
|
||||
"""
|
||||
55
workbook_8708/gold/2631-g4.py
Normal file
55
workbook_8708/gold/2631-g4.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# 줄세우기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def binary_search(v, tails):
|
||||
l, r = 0, len(tails)
|
||||
while l < r:
|
||||
mid = (l+r)//2
|
||||
if tails[mid] >= v:
|
||||
r = mid
|
||||
else:
|
||||
l = mid + 1
|
||||
|
||||
return l
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
tails = [int(input().rstrip())]
|
||||
for _ in range(n-1):
|
||||
now = int(input().rstrip())
|
||||
if tails[-1] < now:
|
||||
tails.append(now)
|
||||
elif tails[-1] == now:
|
||||
continue
|
||||
else:
|
||||
idx = binary_search(now, tails)
|
||||
tails[idx] = now
|
||||
|
||||
print(n - len(tails))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 못 품
|
||||
|
||||
시간 복잡도: O(nlogn)
|
||||
|
||||
해설: 최대 길이의 이미 정렬되어 있는 애들을 제외한 애들을 움직이면 된다. -> LIS(가장 긴 증가하는 부분 수열)
|
||||
두 가지 방법이 있는데,
|
||||
1) dp[i]는 i번째가 맨 끝인 증가하는 부분 수열의 길이라고 할 때, 이중 for문으로 dp[i]를 볼때 j<i인 arr[j]와 dp[j]를 보면서 dp[i]를 갱신하는 방법이다.
|
||||
-> O(n^2)
|
||||
2) tails[i]는 i+1 길이의 증가하는 부분 수열들 중에 맨 끝값 중 최소값이라고 할 때(2 5 8, 2 4 6이 있으면 tails[2]=6),
|
||||
지금 보는 값이 tails[-1]보다 크다면 tails.append()로 최장 증가 부분 수열의 고점을 높이고,
|
||||
지금 보는 값이 tails[-1]보다 같다면 그냥 넘어가고,
|
||||
지금 보는 값이 tails[-1]보다 작다면 tails의 어디에 들어갈지 이분탐색으로 확인해서,
|
||||
그 인덱스의 값을 교체함으로써 tails[idx]에 최대한 작은 수를 놓고 앞으로의 가능성을 높인다.(tails=[2, 5, 8] 이때 4가 들어오면 tails=[2, 4, 8])
|
||||
이렇게 하면 최장 증가 부분 수열의 길이를 O(nlogn)에 구할 수 있지만, 실제 수열은 모른다. -> 따로 기록해두어야 함.
|
||||
|
||||
"""
|
||||
63
workbook_8708/gold/2668-g5.py
Normal file
63
workbook_8708/gold/2668-g5.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# 숫자 고르기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def dfs(v, g, n):
|
||||
visited = [0] * (n+1)
|
||||
stack = [v]
|
||||
record = [v]
|
||||
|
||||
while stack:
|
||||
now = stack.pop()
|
||||
if visited[now]:
|
||||
break
|
||||
visited[now] = 1
|
||||
w = g[now]
|
||||
stack.append(w)
|
||||
record.append(w)
|
||||
|
||||
target = record.pop()
|
||||
result = set()
|
||||
result.add(target)
|
||||
while record and record[-1] != target:
|
||||
result.add(record.pop())
|
||||
|
||||
return result
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
g = {}
|
||||
result = set()
|
||||
for i in range(1, n+1):
|
||||
g[i] = int(input().rstrip())
|
||||
|
||||
for i in range(1, n+1):
|
||||
if i in result:
|
||||
continue
|
||||
result.update(dfs(i, g, n))
|
||||
|
||||
print(len(result))
|
||||
for v in sorted(result):
|
||||
print(v)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 몰라
|
||||
|
||||
시간 복잡도: 한 노드당 한번씩만 방문하기 때문에 O(n)이다.
|
||||
|
||||
해설: 그래프 모양에서 원형 부분에 해당하는 노드들이 답이라는 것은 금방 알았는데 구현이 어려웠다.
|
||||
dfs로 구현했다.
|
||||
본인 노드를 다시 만나게 되면 역으로 추적을 해야하기 때문에 record에 들어온 순서를 스택으로 기록하였고,
|
||||
당연하게도 이미 result에 답으로 채택된 노드들은 dfs 탐색을 시작하지 않았다.
|
||||
하지만 위 방식은 진출차수가 무조건 1이기 때문에 가능한 일이었다.
|
||||
만약 진출차수가 1이상이었다면(제한이 없었다면) 본인 노드가 다시 만나서가 아닌, 여러 곳에서 온 것으로도 반복될 수 있기 때문이다.
|
||||
이런 경우에는 dfs 재귀로 상태관리를 미방문(0), 보는중(1), 끝(2) 이렇게 3가지로 나눠서 진행해야한다.
|
||||
"""
|
||||
55
workbook_8708/gold/4485-g4.py
Normal file
55
workbook_8708/gold/4485-g4.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# 녹색 옷 입은 애가 젤다지?
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
move = [(1,0), (-1, 0), (0, 1), (0, -1)]
|
||||
num = 1
|
||||
while 1:
|
||||
n = int(input().rstrip())
|
||||
if n == 0:
|
||||
break
|
||||
|
||||
grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
result = [[float('inf') for _ in range(n)] for _ in range(n)]
|
||||
|
||||
h = []
|
||||
heapq.heappush(h, (grid[0][0], 0, 0))
|
||||
result[0][0] = grid[0][0]
|
||||
|
||||
while h:
|
||||
v, x, y = heapq.heappop(h)
|
||||
|
||||
for dx, dy in move:
|
||||
now_x, now_y = x+dx, y+dy
|
||||
if now_x >= n or now_x < 0 or now_y >= n or now_y < 0:
|
||||
continue
|
||||
now_v = result[x][y] + grid[now_x][now_y]
|
||||
if now_v < result[now_x][now_y]:
|
||||
result[now_x][now_y] = now_v
|
||||
heapq.heappush(h, (now_v, now_x, now_y))
|
||||
|
||||
print(f"Problem {num}: {result[n-1][n-1]}")
|
||||
num += 1
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: 모든 정점을 다 들렸다가 가는 경우에 n^2만큼 봐야하고, 정점 하나를 볼때마다 힙 정렬에 의해 logn만큼 걸린다.
|
||||
따라서 전체 시간복잡도는 O(n^2logn)이다.
|
||||
|
||||
해설: dp로 하려고 했지만 어디서 시작해서 어느 방향으로 채워야 확정인지 나오질 않기 때문에 dp는 불가능 하다.
|
||||
그렇다면 결국 (0,0)에서 (n-1,n-1)로 가는 최단거리를 구해야하고 그 와중에 가중치가 있기 때문에 다익스트라로 풀 수 있다.
|
||||
기본 구현 방식대로 진행하되, 정점간의 연결을 상하좌우로 하면 된다.
|
||||
내가 푼 방식에서 힙에서 꺼냈을 때 v가 result[x][y]보다 크다면 더 볼 필요 없고, (n-1,n-1)이 점이 꺼내졌다면 거기서 다른
|
||||
곳으로 더 갈 필요는 없기 때문에 끝내는 로직을 추가하면 좀 더 빨라질 수 있다.
|
||||
"""
|
||||
49
workbook_8708/gold/5972-g5.py
Normal file
49
workbook_8708/gold/5972-g5.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# 택배 배송
|
||||
|
||||
import sys
|
||||
import heapq as h
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
g = {i+1: [] for i in range(n)}
|
||||
dk = [float('inf') for _ in range(n+1)]
|
||||
|
||||
for _ in range(m):
|
||||
v, w, k = map(int, input().rstrip().split())
|
||||
g[v].append((k, w))
|
||||
g[w].append((k, v))
|
||||
|
||||
heap = []
|
||||
h.heappush(heap, (0, 1))
|
||||
dk[1] = 0
|
||||
while heap:
|
||||
now_dist, now_v = h.heappop(heap)
|
||||
|
||||
if now_dist > dk[now_v]:
|
||||
continue
|
||||
|
||||
for nxt_k, nxt_v in g[now_v]:
|
||||
new_dist = dk[now_v]+nxt_k
|
||||
if new_dist < dk[nxt_v]:
|
||||
dk[nxt_v] = min(dk[nxt_v], dk[now_v]+nxt_k)
|
||||
h.heappush(heap, (new_dist, nxt_v))
|
||||
|
||||
print(dk[n])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 47분
|
||||
|
||||
시간 복잡도: 간선만큼 진행하는데 이때 heap 정렬이 매번 일어나기 때문에 O(mlogn)이다.
|
||||
|
||||
해설: 시작지점에서 끝지점까지의 가중치에 따른 최단거리를 구하는 것이기 때문에 다익스트라를 활용하면 된다.
|
||||
현재 노드에서 다음 노드까지의 최단거리가 아니라 전체 다익스트라 결과에서 가장 최단거리인 노드로 다시 시작을 하는 것이었다.
|
||||
이렇게 진행하면 visited를 쓰지 않아도, heap에 중복된 노드가 들어갈 수 있지만 거리가 먼 것은 배제하기 때문에 지장이 없다.
|
||||
"""
|
||||
42
workbook_8708/gold/7490-g5.py
Normal file
42
workbook_8708/gold/7490-g5.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# 0 만들기
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
OPERATOR = [" ", "+", "-"] # 아스키 순서
|
||||
|
||||
def dfs(depth, n, exp):
|
||||
if depth == n:
|
||||
exp += str(depth)
|
||||
if eval(exp.replace(" ", "")) == 0:
|
||||
print(exp)
|
||||
return
|
||||
|
||||
for op in OPERATOR:
|
||||
dfs(depth+1, n, exp+str(depth)+op)
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
dfs(1, n, "")
|
||||
print()
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 몰라
|
||||
|
||||
시간 복잡도: 전체 탐색이고, 연산자가 8칸에 3가지씩 가능하기 때문에 3^8이고, 테스트 케이스가 최대 9개이므로 (3^8)*9.
|
||||
따라서 3^10이다. 60000정도이다.
|
||||
|
||||
해설: 전체를 다 해봐야지 알 수 있다는 것을 파악한 후 모든 경우의 수를 어떻게 확인할지가 관건이었다.
|
||||
중첩 for문을 하려고 했으나 중첩이 너무 많아져서 dfs로 완전 탐색을 하기로 했다.
|
||||
문자열 수식을 계산하는 것을 eval()을 몰라서 split하고 어떻게 해서 계산하려고 했는데 그냥 eval() 썼다.
|
||||
"""
|
||||
94
workbook_8708/gold/9935-g4.py
Normal file
94
workbook_8708/gold/9935-g4.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# 문자열 폭발
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
stack = []
|
||||
result = ""
|
||||
bomb = input().rstrip()
|
||||
|
||||
for ch in s:
|
||||
stack.append(ch)
|
||||
if stack[-1] == bomb[-1]:
|
||||
idx = 0
|
||||
while len(stack) >= len(bomb) and idx < len(bomb):
|
||||
if stack[-1-idx] != bomb[-1-idx]:
|
||||
result += "".join(stack)
|
||||
stack = []
|
||||
break
|
||||
idx += 1
|
||||
if idx == len(bomb):
|
||||
for _ in range(len(bomb)):
|
||||
stack.pop()
|
||||
|
||||
result += "".join(stack)
|
||||
if not result:
|
||||
print("FRULA")
|
||||
else:
|
||||
print(result)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 34분
|
||||
|
||||
시간 복잡도: 한 문자당 상수번 다뤄지기 때문에 O(n)이다.
|
||||
|
||||
해설: 처음에는 bomb 문자열의 순서와 쌍을 기록하는 방식으로 연결관계를 계속 파악하려고 했다. 그렇다보니 조건 분기가 많아졌고,
|
||||
틀렸을 때는 어디가 잘못됐을지 감도 안 잡혀서 과감하게 다른 풀이로 전향했다.
|
||||
좀 더 생각을 해보니 문자를 볼때 bomb의 마지막 문자일때만 이미 들어갔던 것들을 쭉 보고 만약에 bomb이 아니라면
|
||||
지금까지 본 문자열은 앞으로도 절대 폭발할 수 없다는 것을 깨달았다.
|
||||
따라서 방금 과정을 진행한 후 폭발하지 않았다면 stack에 있는 모든 문자를 다시는 보지 않기 위해 stack에서 빼고 문자열로 바꿔놓는다.
|
||||
만약 폭발했다면 stack에 남아있는 것들이 또 연결되어 폭발할 수 있으므로 남겨놓는다.
|
||||
"""
|
||||
|
||||
# def solution(): # 12:25~ 1:15 실패
|
||||
# s = input().rstrip()
|
||||
# bomb = {ch: i+1 for i, ch in enumerate(input().rstrip())} # start 1~
|
||||
# # print(bomb)
|
||||
# dq = deque([])
|
||||
# group = 0
|
||||
# no_group = -1
|
||||
# for i, ch in enumerate(s):
|
||||
# # b = -1
|
||||
# bomb_order = bomb.get(ch, -1)
|
||||
# if bomb_order == 1:
|
||||
# group += 1
|
||||
# dq.append((bomb_order, group, i))
|
||||
# # b = 1
|
||||
|
||||
# elif not dq:
|
||||
# dq.append((bomb_order, no_group, i))
|
||||
# # b = 2
|
||||
|
||||
# elif bomb_order == len(bomb) and dq[-1][0] == len(bomb)-1:
|
||||
# now_group = dq[-1][1]
|
||||
# while dq and dq[-1][1] == now_group:
|
||||
# dq.pop()
|
||||
# # b = 3
|
||||
# elif bomb_order == dq[-1][0]+1:
|
||||
# dq.append((bomb_order, dq[-1][1], i))
|
||||
# # b = 4
|
||||
|
||||
# else:
|
||||
# dq.append((bomb_order, no_group, i))
|
||||
# # b = 5
|
||||
# # print(b, dq)
|
||||
|
||||
# result = ""
|
||||
# while dq:
|
||||
# result += s[dq.popleft()[2]]
|
||||
|
||||
# if not result:
|
||||
# print("FRULA")
|
||||
# else:
|
||||
# print(result)
|
||||
|
||||
# return
|
||||
|
||||
|
||||
# solution()
|
||||
46
workbook_8708/silver/10431-s5.py
Normal file
46
workbook_8708/silver/10431-s5.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# 줄세우기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def test(students):
|
||||
line = [float('inf')] * 20
|
||||
count = 0
|
||||
|
||||
for i, s in enumerate(students):
|
||||
now_idx = 0
|
||||
while 1:
|
||||
if line[now_idx] > s:
|
||||
break
|
||||
now_idx += 1
|
||||
for j in range(i-1, now_idx-1, -1):
|
||||
line[j+1] = line[j]
|
||||
count += 1
|
||||
line[now_idx] = s
|
||||
|
||||
return count
|
||||
|
||||
def solution():
|
||||
p = int(input().rstrip())
|
||||
|
||||
for _ in range(p):
|
||||
test_case = list(map(int, input().rstrip().split()))
|
||||
print(test_case[0], test(test_case[1:]))
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 33분
|
||||
|
||||
시간 복잡도: 새로운 학생이 line에 들어올때마다 원래 있던 모든 학생이 움직이는 경우가 최대이므로
|
||||
학생 수를 n이라고 하면 학생 당 (n-1), (n-2),... 0 이므로 O(n^2)인데, 이 문제는 20명 고정이므로
|
||||
19*20/2 = 190 이다.
|
||||
|
||||
해설: 기본 line을 float('inf')로 세팅함으로써 사람이 없는 경우는 맨 뒤에 두고 없는 사람 취급을 한다.
|
||||
세팅 후 순서대로 한명씩 line에 넣는데 이때 나보다 큰 가장 앞에 있는 사람을 찾아야 하기 때문에
|
||||
그냥 맨 처음부터 보다가 나보다 큰 사람이 있으면 그 index에 내가 서고, 뒤에 있는 사람들을
|
||||
한 칸씩 뒤로 밀면 된다. 뒤로 밀때는 지금까지 line에 있는 사람 수에서 내가 들어가야할 index까지
|
||||
거꾸로 오면서 한 칸씩 뒤로 밀면 된다. 이때 count+1을 해주고 결과값 count를 반환하고 출력.
|
||||
"""
|
||||
40
workbook_8708/silver/1138-s2.py
Normal file
40
workbook_8708/silver/1138-s2.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 한 줄로 서기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
blank = [i for i in range(n)]
|
||||
|
||||
info = list(map(int, input().rstrip().split()))
|
||||
|
||||
result = [0] * n
|
||||
for i in range(n):
|
||||
result[blank[info[i]]] = i+1
|
||||
blank.pop(info[i])
|
||||
|
||||
print(*result)
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: 원하는 것을 pop하는 것은 O(n)이 걸릴 수 있고, 그것을 n번 하므로 O(n^2)이다.
|
||||
blank의 칸을 dict로 관리하면 O(n)으로 가능할 것 같다.
|
||||
|
||||
해설: 본인보다 키가 큰 사람이 왼쪽에 몇 명인지 안다는 것은 본인보다 모두가 키가 큰 구성에서는 몇 등인지 안다는 것이다.
|
||||
그렇기 때문에 키가 1인 사람부터 등수를 구할 수 있고, 구한다음에는 1을 배제하고 2가 키가 제일 작은 구성에서 몇 등인지
|
||||
구하는 방식으로 진행하면 된다.
|
||||
이때, 이미 1이 차지한 등수를 제외하고 남은 칸들 중에 나온 등수대로 넣으면 된다.
|
||||
따라서 빈 자리를 의미하는 blank 리스트에서 남는 칸들을 확인할 수 있고, info+1이 본인의 등수이지만 blank는 0부터 시작하므로
|
||||
그냥 blank[info]를 하면 본인이 차지해야하는 칸이 나온다.
|
||||
그 후 blank에서 차지한 칸을 지워주면 나오는 등수대로 잘 들어갈 수 있다.
|
||||
"""
|
||||
62
workbook_8708/silver/11501-s2.py
Normal file
62
workbook_8708/silver/11501-s2.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# 주식
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def calculate_revenue(n, prices):
|
||||
total = 0
|
||||
q = deque([prices[0]])
|
||||
up = 0
|
||||
if prices[0] <= prices[1]:
|
||||
up = 1
|
||||
else:
|
||||
up = 0
|
||||
|
||||
for i in range(1, n):
|
||||
if len(q) != 0 and i == n-1 and prices[i] >= q[-1]:
|
||||
high = q.pop() if i != n-1 else prices[i]
|
||||
while len(q) >= 1 and q[0] > high:
|
||||
q.popleft()
|
||||
while len(q) >= 1:
|
||||
total += (high-q.pop())
|
||||
|
||||
if not up:
|
||||
if len(q) != 0 and prices[i] > q[-1]:
|
||||
up = 1
|
||||
q.append(prices[i])
|
||||
continue
|
||||
|
||||
if len(q) != 0 and (prices[i] < q[-1] or i == n-1):
|
||||
high = q.pop() if i != n-1 else prices[i]
|
||||
while len(q) >= 1 and q[0] > high:
|
||||
q.popleft()
|
||||
while len(q) >= 1:
|
||||
total += (high-q.pop())
|
||||
up = 0
|
||||
q.append(prices[i])
|
||||
|
||||
return total
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
prices = list(map(int, input().rstrip().split()))
|
||||
print(calculate_revenue(n, prices))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간:
|
||||
|
||||
시간 복잡도:
|
||||
|
||||
해설:
|
||||
"""
|
||||
62
workbook_8708/silver/1205-s4.py
Normal file
62
workbook_8708/silver/1205-s4.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# 등수 구하기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def binary_search(lst, v):
|
||||
start, end = 0, len(lst)
|
||||
|
||||
while start < end:
|
||||
mid = (start+end) // 2
|
||||
if lst[mid] <= v:
|
||||
end = mid
|
||||
else:
|
||||
start = mid+1
|
||||
|
||||
return start
|
||||
|
||||
def solution():
|
||||
n, new_score, p = map(int, input().rstrip().split())
|
||||
|
||||
if n == 0:
|
||||
print(1)
|
||||
return
|
||||
|
||||
scores = list(map(int, input().rstrip().split()))
|
||||
|
||||
|
||||
if n == p and new_score <= scores[-1]:
|
||||
print(-1)
|
||||
return
|
||||
|
||||
result = binary_search(scores, new_score)
|
||||
|
||||
print(result+1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간 (이분탐색 여러 종류를 공부하면서 하느라 좀 걸렸다..)
|
||||
|
||||
시간 복잡도: O(logn)
|
||||
|
||||
해설: 이분탐색으로 들어갈 곳을 정하고, 이때, 값이 같다면 맨 앞에 놓을 수 있도록 처음으로 lst[mid] > target이 되는 곳을 찾으면 된다.
|
||||
이게 이분탐색 lower_bound이다. 여기서 찾고자 하는 것과 배열 상태에 따라 조건을 잘 설정해야되는데, 우리가 원하는 것은 3번이다.
|
||||
오름차순이라면 x 이상, 초과를 찾을 것이고, 내림차순이라면 x 이하, 미만을 찾는 것이 일반화하는데 편하다.
|
||||
1. 오름차순 배열에서 처음 x 이상을 찾는다면 lst[mid] >= x 이고, mid도 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
2. 오름차순 배열에서 처음 x 초과를 찾는다면 lst[mid] > x 이고, mid가 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
3. 내림차순 배열에서 처음 x 이하를 찾는다면 lst[mid] <= x 이고, mid가 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
4. 내림차순 배열에서 처음 x 미만을 찾는다면 lst[mid] < x 이고, mid가 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
|
||||
아무튼 가장 중요한 것은 현재 mid가 답이 될 수 있는가에 대한 여부와 왼쪽과 오른쪽 중 어디가 답 가능성이 있는 방향인지를 보면
|
||||
1. if 조건과 r, l의 매칭 & 2. r, l에 mid +1을 할지 말지를 정할 수 있다.
|
||||
|
||||
그 외에 이 문제는 경계에 대한 것이었기 때문에 l < r 조건에 [l, r) 구간이었는데,
|
||||
원소를 특정하는 것은 mid를 보고 아니면 버리기 때문에 mid +-1은 항상 해주고, 구간도 [l, r]에 조건도 l <= r이다.
|
||||
"""
|
||||
64
workbook_8708/silver/1244-s4.py
Normal file
64
workbook_8708/silver/1244-s4.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# 스위치 켜고 끄기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def work_mode1(s, s_state, s_num):
|
||||
mul = 1
|
||||
idx = s_num * mul
|
||||
while idx <= s:
|
||||
s_state[idx] = 1 - s_state[idx]
|
||||
mul += 1
|
||||
idx = s_num * mul
|
||||
return
|
||||
|
||||
def work_mode2(s, s_state, s_num):
|
||||
gap = 1
|
||||
s_state[s_num] = 1 - s_state[s_num]
|
||||
while s_num + gap <= s and s_num - gap >= 1:
|
||||
if s_state[s_num + gap] != s_state[s_num - gap]:
|
||||
break
|
||||
s_state[s_num + gap] = 1 - s_state[s_num + gap]
|
||||
s_state[s_num - gap] = 1 - s_state[s_num - gap]
|
||||
gap += 1
|
||||
return
|
||||
|
||||
WORK = {
|
||||
1: work_mode1,
|
||||
2: work_mode2
|
||||
}
|
||||
|
||||
def solution():
|
||||
s = int(input().rstrip())
|
||||
s_state = [-1] + list(map(int, input().rstrip().split()))
|
||||
n = int(input().rstrip())
|
||||
|
||||
for _ in range(n):
|
||||
mode, s_num = map(int, input().rstrip().split())
|
||||
now_work = WORK[mode]
|
||||
now_work(s, s_state, s_num)
|
||||
|
||||
s_state = s_state[1:]
|
||||
|
||||
for i in range(s//20+1):
|
||||
start, end = i*20, (i*20)+20
|
||||
print(*s_state[start:end])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
"""
|
||||
걸린 시간: 16분
|
||||
|
||||
시간 복잡도: 남자, 여자 둘 다 한 턴에 스위치 전체 길이인 s에 대해 O(s)이므로 전체 시간 복잡도는 학생 수가 n일 때, O(s*n) 이다.
|
||||
|
||||
해설: 남자(mode1), 여자(mode2)로 작업을 나눠서 배수는 1,2,3 올라가면서 시작 버튼에 곱해주고, 옆으로 확인은 gap을 +1 해주면서
|
||||
확인한다. while 반복문의 기본 규칙은 1과 s 사이의 범위이고, mode2에서 추가 escape는 보고 있는 두 스위치의 상태가 다를 때이다.
|
||||
메인 함수에서는 mode에 맞게 work 함수를 할당 받은 후 작업을 진행하고, 20단위로 끊어서 출력한다.
|
||||
추가로 worker 클래스를 만들어서 상속 받아서 하면 좀 더 안전한 코드가 될 것 같다.
|
||||
|
||||
"""
|
||||
72
workbook_8708/silver/1260-s2.py
Normal file
72
workbook_8708/silver/1260-s2.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# DFS와 BFS
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def dfs(n, g, v):
|
||||
result = []
|
||||
visited = [0]*(n+1)
|
||||
stack = [v]
|
||||
|
||||
while stack:
|
||||
w = stack.pop()
|
||||
if visited[w]:
|
||||
continue
|
||||
|
||||
result.append(w)
|
||||
visited[w] = 1
|
||||
for i in range(len(g[w])-1, -1, -1):
|
||||
stack.append(g[w][i])
|
||||
|
||||
return result
|
||||
|
||||
def bfs(n, g, v):
|
||||
result = []
|
||||
visited = [0]*(n+1)
|
||||
q = deque([v])
|
||||
visited[v] = 1
|
||||
|
||||
while q:
|
||||
w = q.popleft()
|
||||
result.append(w)
|
||||
for k in g[w]:
|
||||
if not visited[k]:
|
||||
q.append(k)
|
||||
visited[k] = 1
|
||||
return result
|
||||
|
||||
def solution():
|
||||
n, m, v = map(int, input().rstrip().split())
|
||||
|
||||
g = [[] for _ in range(n+1)]
|
||||
|
||||
for _ in range(m):
|
||||
v1, v2 = map(int, input().rstrip().split())
|
||||
g[v1].append(v2)
|
||||
g[v2].append(v1)
|
||||
|
||||
for i in range(1, n+1):
|
||||
g[i].sort()
|
||||
|
||||
print(*dfs(n, g, v))
|
||||
print(*bfs(n, g, v))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 34분
|
||||
|
||||
시간 복잡도: 간선 수에 따라 for문을 돌아보는 차이가 난다. 또한 어디 노드에 연결이 얼마나 되어 있느냐에 따라 sort의 차이도 난다.
|
||||
|
||||
해설: dfs는 시작 노드를 stack에 넣고 pop해가면서 인접 노드를 넣는 방식으로 구현이 가능하다.
|
||||
이때, visited를 pop하고 찍음으로써 이전에 인접한 노드로 나왔더라도 한 번 더 나왔을 때 다시 넣을 수 있게 한다.
|
||||
이는 깊이 탐색을 위해 뒤에서 나올수록 우선순위가 높아짐을 의미한다.
|
||||
bfs는 시작 노드를 queue에 넣고 popleft 해가면서 인접 노드를 넣는 방식으로 구현이 가능하다.
|
||||
이때, visited를 queue에 append 하면서 찍음으로써 이후에 인접한 노드로 또 나왔을 경우 다시 못 들어가게 한다.
|
||||
이는 너비 탐색을 위해 먼저 나왔을수록 우선순위가 높음을 의미한다.
|
||||
"""
|
||||
61
workbook_8708/silver/1283-s1.py
Normal file
61
workbook_8708/silver/1283-s1.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# 단축키 지정
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_word_first(words, shortcut):
|
||||
for i in range(len(words)):
|
||||
c = words[i][0].upper()
|
||||
if not shortcut.get(c, 0):
|
||||
shortcut[c] = 1
|
||||
return i
|
||||
return -1
|
||||
|
||||
def check_word(word, shortcut):
|
||||
for i in range(len(word)):
|
||||
c = word[i].upper()
|
||||
if not shortcut.get(c, 0):
|
||||
shortcut[c] = 1
|
||||
return i
|
||||
return -1
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
shortcut = {}
|
||||
|
||||
for _ in range(n):
|
||||
option = input().rstrip().split()
|
||||
shortcut_idx = check_word_first(option, shortcut)
|
||||
|
||||
if shortcut_idx != -1:
|
||||
option[shortcut_idx] = f"[{option[shortcut_idx][0]}]" + option[shortcut_idx][1:]
|
||||
print(*option)
|
||||
continue
|
||||
|
||||
idx = 0
|
||||
while idx < len(option):
|
||||
shortcut_idx = check_word(option[idx], shortcut)
|
||||
if shortcut_idx != -1:
|
||||
option[idx] = option[idx][:shortcut_idx] + f"[{option[idx][shortcut_idx]}]" + option[idx][shortcut_idx+1:]
|
||||
break
|
||||
idx += 1
|
||||
|
||||
print(*option)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 41분
|
||||
|
||||
시간 복잡도: 완전 탐색이기 때문에 O(5*10*n)이다.
|
||||
|
||||
해설: 30개의 옵션에 1개 옵션 당 5개 이하 단어와 1개의 단어에 10개 이하의 알파벳이면 다 돌아봤자 1500이다.
|
||||
따라서 조건대로 구현하면 된다. 대소문자를 구분하지 않기 때문에 다 upper로 만들어서 현재 사용된 옵션을 기록한다.
|
||||
단어 첫 글자들을 보며 옵션 설정하고, 한 단어씩 쭉 보면서 옵션 설정을 한다.
|
||||
옵션을 설정하면 출력 형태를 맞춰서 리스트에 저장하고 마지막에 한번에 출력한다.
|
||||
"""
|
||||
35
workbook_8708/silver/13305-s3.py
Normal file
35
workbook_8708/silver/13305-s3.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# 주유소
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
dist = list(map(int, input().rstrip().split()))
|
||||
price = list(map(int, input().rstrip().split()))
|
||||
|
||||
least_price = float('inf')
|
||||
|
||||
result = 0
|
||||
for i in range(n-1):
|
||||
if price[i] < least_price:
|
||||
least_price = price[i]
|
||||
result += (dist[i]*least_price)
|
||||
|
||||
|
||||
print(result)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
|
||||
"""
|
||||
걸린 시간: 12분
|
||||
|
||||
시간 복잡도: dist 길이만큼 한 번 돌기 때문에 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 현재 지역 다음에 본인보다 더 싼게 있으면 거기까지만 가고 그 다음부터는 싼 곳에서 기름을 사야한다.
|
||||
가장 쌌던 가격을 계속 기록해가면서 price를 마지막-1 까지 순회하면 끝.
|
||||
"""
|
||||
77
workbook_8708/silver/1406-s2.py
Normal file
77
workbook_8708/silver/1406-s2.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# 에디터
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def l(left_q, right_q):
|
||||
if len(left_q) >= 1:
|
||||
right_q.appendleft(left_q.pop())
|
||||
return
|
||||
|
||||
def d(left_q, right_q):
|
||||
if len(right_q) >= 1:
|
||||
left_q.append(right_q.popleft())
|
||||
return
|
||||
|
||||
def b(left_q):
|
||||
if len(left_q) >= 1:
|
||||
left_q.pop()
|
||||
return
|
||||
|
||||
def p(left_q, w):
|
||||
left_q.append(w)
|
||||
return
|
||||
|
||||
COMMANDS = {
|
||||
"L": l,
|
||||
"D": d,
|
||||
"B": b,
|
||||
"P": p,
|
||||
}
|
||||
|
||||
def excute(left_q, right_q, *c):
|
||||
command = COMMANDS.get(c[0], None)
|
||||
if c[0] == "P":
|
||||
command(left_q, c[1])
|
||||
elif c[0] == "L" or c[0] == "D":
|
||||
command(left_q, right_q)
|
||||
elif c[0] == "B":
|
||||
command(left_q)
|
||||
else:
|
||||
return
|
||||
return
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
m = int(input().rstrip())
|
||||
|
||||
left_q = deque(list(s))
|
||||
right_q = deque([])
|
||||
|
||||
for _ in range(m):
|
||||
excute(left_q, right_q, *(input().rstrip().split()))
|
||||
|
||||
result = list(left_q) + list(right_q)
|
||||
print("".join(result))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: deque는 pop이나 append가 어디든 O(1)이므로 명령어 수행은 항상 O(1)이고, m번 명령을 반복하기 때문에 O(m)이다.
|
||||
그 후 마지막에 두 deque를 합쳐서 출력하기 때문에 n개의 단어에서 m만큼 글자가 추가 되었다면 O(n+m)이다.
|
||||
따라서 전체 시간복잡도는 O(n+m)이다.
|
||||
|
||||
해설: 커서를 기준으로 양쪽에 deque를 배치한 후 l, d로 커서를 움직이면 양쪽 deque에서 요소들을 옮기고, b, p로 요소를 지우거나 추가하면
|
||||
커서 기준 왼쪽으로 동작한다고 했으므로 왼쪽 deque로 요소를 조정한다. 마지막에 두 deque를 list로 만들어서 합치고 출력하면 끝
|
||||
|
||||
확장성을 위해 dispatch 전략을 사용했지만 l,d,b,p의 인자가 달라서 excute 함수에서 또 분기를 했다. -> l,d,b,p의 인자를 같게 하면 됨
|
||||
자료구조가 deque에서 다른 것으로 바뀐다면 다 수정해야 하기 때문에 결합도가 너무 높다.
|
||||
-> 추상화 계층 하나를 추가해서 Editor라는 클래스를 만들고 거기다가 기능들 쓴 다음에 l,d,b,p가 그걸 받아오면 나중에 Editor 클래스만 바꾸면 됨
|
||||
"""
|
||||
40
workbook_8708/silver/1446-s1.py
Normal file
40
workbook_8708/silver/1446-s1.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 지름길
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, d = map(int, input().rstrip().split())
|
||||
shortcut = {}
|
||||
for _ in range(n):
|
||||
start, end, cost = map(int, input().rstrip().split())
|
||||
if end > d:
|
||||
continue
|
||||
if not shortcut.get(end, []):
|
||||
shortcut[end] = []
|
||||
shortcut[end].append((start, cost))
|
||||
|
||||
dp = [0] * (d+1)
|
||||
|
||||
for i in range(1, d+1):
|
||||
shortcut_list = shortcut.get(i, [])
|
||||
dp[i] = min(min([dp[s]+c for s, c in shortcut_list]) if shortcut_list else float('inf'), dp[i-1]+1)
|
||||
|
||||
print(dp[d])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: 모든 지점에 대해 dp 값을 구하는데, 이때 한 지점은 연결된 지름길만큼 반복한다.
|
||||
하지만 지름길 하나 당 한번만 보기 때문에 전체 시간복잡도는 O(n+d)이다.
|
||||
|
||||
해설: 지름길의 도착 위치 기준으로 그냥 가는 것과 여러 지름길 중 하나를 선택하는 것과 같이
|
||||
여러 개를 비교해야했다. 그리고 비교를 하는 것이 과거의 지점에서 계산을 하는 것이기 때문에 dp를 생각했다.
|
||||
현재 지점의 dp를 계산할 때 이 곳에 올 수 있는 모든 경우의 수 중 cost가 최소인 것을 구하면 된다.
|
||||
따라서 지름길을 통해 오는 것과 바로 한 칸 전 위치에서 +1로 오는 경우 중 구하면 된다.
|
||||
"""
|
||||
74
workbook_8708/silver/14940-s1.py
Normal file
74
workbook_8708/silver/14940-s1.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# 쉬운 최단거리
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def find_target(grid, n, m):
|
||||
for i in range(n):
|
||||
for j in range(m):
|
||||
if grid[i][j] == 2:
|
||||
target = (i, j)
|
||||
return target
|
||||
return (-1, -1)
|
||||
|
||||
def set_zero_land(grid, visited, n, m):
|
||||
for i in range(n):
|
||||
for j in range(m):
|
||||
if grid[i][j] == 0:
|
||||
visited[i][j] = 0
|
||||
return
|
||||
|
||||
|
||||
def bfs(grid, target, n, m):
|
||||
dr = [1, -1, 0, 0]
|
||||
dc = [0, 0, 1, -1]
|
||||
visited = [[-1]*m for _ in range(n)]
|
||||
set_zero_land(grid, visited, n, m)
|
||||
q = deque([target])
|
||||
visited[target[0]][target[1]] = 0
|
||||
|
||||
while q:
|
||||
r, c = q.popleft()
|
||||
for i in range(4):
|
||||
now_r, now_c = r+dr[i], c+dc[i]
|
||||
if now_r == target[0] and now_c == target[1]:
|
||||
continue
|
||||
if 0 <= now_r < n and 0 <= now_c < m and grid[now_r][now_c] != 0 and visited[now_r][now_c] == -1:
|
||||
q.append((now_r, now_c))
|
||||
visited[now_r][now_c] = visited[r][c] + 1
|
||||
|
||||
return visited
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
target = find_target(grid, n, m)
|
||||
|
||||
result = bfs(grid, target, n, m)
|
||||
|
||||
for i in range(n):
|
||||
print(*result[i])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 55분
|
||||
|
||||
시간 복잡도: target 찾고, 0 세팅 하는데 O(nm)이고,
|
||||
bfs는 한 노드마다 4번의 인접 노드를 확인하므로 O(4nm)
|
||||
전체 시간복잡도는 O(nm)이다.
|
||||
|
||||
해설: 각 점에서 도착지까지 계속 찾아가는건 말이 안되고, 인접 점의 결과에 +1을 하는 식으로
|
||||
O(1)에 찾도록 생각을 하였다. dp가 떠올랐지만,
|
||||
target 지점을 기준으로 +1씩 해야하기 때문에 target이 중간 어딘가에 있으면 dp 테이블을 채우기 애매했다.
|
||||
따라서 너비우선 탐색을 떠올렸고, bfs로 진행했다.
|
||||
조건들이 조금 귀찮아서 몇 번 틀렸는데, 0인 땅은 그냥 0이고, 1인데 못 가는 땅은 -1로 출력을 해야했다.
|
||||
따라서 bfs 세팅에서 기본 visited를 -1로 잡고, 0인 땅은 0으로 초기화 해주는 작업을 했다.
|
||||
"""
|
||||
69
workbook_8708/silver/1515-s2.py
Normal file
69
workbook_8708/silver/1515-s2.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# 수 이어 쓰기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_parttern(now, target):
|
||||
idx = 0
|
||||
len_target = len(target)
|
||||
for c1 in now:
|
||||
while idx < len_target:
|
||||
if c1 == target[idx]:
|
||||
idx += 1
|
||||
break
|
||||
else:
|
||||
idx += 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
len_s = len(s)
|
||||
i = 0
|
||||
target = 0
|
||||
while i < len_s:
|
||||
target += 1
|
||||
j = i
|
||||
while j < len_s and int(s[i:j+1]) <= target:
|
||||
now = s[i:j+1]
|
||||
if check_parttern(now, str(target)):
|
||||
j += 1
|
||||
else:
|
||||
break
|
||||
i = j
|
||||
print(target)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 53분
|
||||
|
||||
시간 복잡도: s의 길이가 3000까지가 최대라고 했기 때문에 최악의 경우 0이 3000개 있으면
|
||||
target이 30000까지 간다. 즉, len(s) = n, max(target) = 10n = T이다.
|
||||
근데 s의 한 숫자는 한번씩만 보는데 내 코드는 한번 볼때 다음것이 패턴이
|
||||
가능하다면 중복해서 보기 때문에 O(j^2)이긴 하지만 이렇게 한번하면 그만큼 가장 최근의 것은 1번 본다.
|
||||
따라서 전체 시간복잡도는 O((n+T)^2) 정도이다.
|
||||
근데 s의 i번째 수를 보는 것의 중복을 없애면 O(TlogT)가 될 수 있을 것 같다.(log 밑은 10)
|
||||
|
||||
|
||||
|
||||
해설: 처음엔 문제 이해가 좀 어려웠는데 써가면서 하니까 이해가 됐다.
|
||||
그리고 주어진 테스트 케이스가 엄청 복잡한 것을 보면 규칙 찾아서 하는 것이라는 걸 의심해보자.
|
||||
1~10까지를 한 세트라고 했을 때 지금 보는 숫자보다 작거나 같은 숫자가 나오면 한 세트가 넘어간 것이다.
|
||||
이걸로 규칙 세워서 가려고 했는데 다음 세트로 넘어갈수록 숫자가 10의 자리나 100의 자리가 생기고, 바뀌고
|
||||
그러기 때문에 쉽지 않았다. -> 주어진 숫자를 쭉 보면서 답이 될 수 있는 숫자를 하나씩 키워나가자.
|
||||
s의 숫자들을 하나씩 보면서 target이 될 수 있는 숫자라면, 즉 target의 substring이라면 s의 다음 숫자를 보고
|
||||
target도 하나 키우는 방식으로 진행했다. 아니라면 당연히 target만 하나 키우기.
|
||||
여기서 substring 구하는 방식을 s의 i번째를 확인했음에도 안쪽 while문으로 i~i+j번째까지 계속 중복 확인을 했다.
|
||||
이 부분을 따로 함수로 빼서 고치든가 했어야 했다.(어차피 그래도 답은 틀림)
|
||||
아무튼 나는 now in target 방법으로 진행했는데, 반례가 존재했다. s의 11이 target의 101을 대표하지 못했다.
|
||||
in으로는 0이 있어서 안되기 때문이다.
|
||||
따라서 target의 한 글자와 s의 한글자씩 보는 방식으로 진행했다.
|
||||
역시 i~i+j번째를 보기까지 중복이 있긴 해서 이 부분을 고쳐야 하긴 하지만 아무튼 통과했다.
|
||||
"""
|
||||
32
workbook_8708/silver/1522-s1.py
Normal file
32
workbook_8708/silver/1522-s1.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# 문자열 교환
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
|
||||
k = s.count("a")
|
||||
k_count = {"a": s[:k].count("a"), "b": s[:k].count("b")}
|
||||
circle = s + s
|
||||
result = k_count["b"]
|
||||
for i in range(1, len(circle)-k):
|
||||
k_count[circle[i-1]] -= 1
|
||||
k_count[circle[i+k-1]] += 1
|
||||
result = min(result, k_count["b"])
|
||||
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 못 품
|
||||
|
||||
시간 복잡도: 전체에서 a의 개수(k)를 세고, k구간씩 옮겨가며 b개수를 슬라이딩 윈도우로 업데이트하기 때문에 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 원형이라고 했기 때문에 같은 것 2배를 해준 문자열을 만든다. 여기서 기존 a가 다 연속이면 되기 때문에
|
||||
a의 개수 k를 구해서 원형에서 k구간씩 확인하며 b를 다 빼주면 되는데, 이때 b개수의 최소값이 답이다.
|
||||
"""
|
||||
44
workbook_8708/silver/1697-s1.py
Normal file
44
workbook_8708/silver/1697-s1.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# 숨바꼭질
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
|
||||
max_len = 100000
|
||||
line = [0 for _ in range(max_len+1)]
|
||||
move = [-1, 1]
|
||||
|
||||
q = deque([n])
|
||||
line[n] = 1
|
||||
|
||||
while q:
|
||||
now = q.popleft()
|
||||
for m in move:
|
||||
now_move = now + m
|
||||
if 0 <= now_move < max_len+1 and line[now_move] == 0:
|
||||
q.append(now_move)
|
||||
line[now_move] = line[now] + 1
|
||||
if 0 <= now*2 < max_len+1 and line[now*2] == 0:
|
||||
q.append(now*2)
|
||||
line[now*2] = line[now] + 1
|
||||
|
||||
print(line[k]-1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 몰라
|
||||
|
||||
시간 복잡도: 한 지점 당 큐에 한 번씩만 들어갔다가 나오기 때문에 전체 지점만큼의 시간이 걸린다. 따라서 O(100000)이다.
|
||||
|
||||
해설: 특정 위치를 볼 때 그 위치로부터 //2, -1, +1 지점에서 +1 한 것들과 기존 지점까지 총 4개 값의 최소값을 가져오면서 dp 테이블을
|
||||
갱신하면 될 것 같았는데, 이렇게 되면 dp 테이블을 채우는 방향에 따라 비교해야하는 4지점이 다 안 채워진 경우가 있다.
|
||||
따라서 bfs로 한번 이동하는 것을 하나의 계층으로 생각해서 진행하면 된다.
|
||||
"""
|
||||
36
workbook_8708/silver/17266-s4.py
Normal file
36
workbook_8708/silver/17266-s4.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# 어두운 굴다리
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
m = int(input().rstrip())
|
||||
x = list(map(int, input().rstrip().split()))
|
||||
result = 0
|
||||
for i in range(1, m):
|
||||
now = (x[i]-x[i-1])//2 if (x[i]-x[i-1])%2==0 else (x[i]-x[i-1])//2 + 1
|
||||
result = max(result, now)
|
||||
|
||||
result = max(result, x[0]-0, n-x[-1])
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 26분
|
||||
|
||||
시간 복잡도: 0에서 첫 번째 위치를 빼는 것이랑, 끝에서 마지막 위치를 빼는 것을 포함하여 약 m번의 연산을 진행한다.
|
||||
m이 n보다 작으므로 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 가로등이 놓일 위치 사이의 거리가 가장 큰 값을 2로 나눈 값이 답이다. 반씩 나눠서 그 구간을 커버해야하기 때문이다.
|
||||
x를 순차적으로 가면서 앞의 위치와 차이//2 중 최대를 찾으면 되는데, 이때, 차이가 홀수인 경우 +1을 해줘야 커버가된다.
|
||||
삼항연산자로 구분했지만 ceil을 하거나 -(-n//2)를 하면 같은 효과를 볼 수 있다.
|
||||
파이썬의 //는 무조건 음의 무한대로 내림하기 때문에 -5 // 2는 -2.5가 -3이 된다. => 올림 효과를 볼 수 있다.
|
||||
마지막으로 0과 n에는 가로등 하나가 온전히 감당해야 하므로 마지막에 비교해주면 끝.
|
||||
"""
|
||||
99
workbook_8708/silver/17484-s3.py
Normal file
99
workbook_8708/silver/17484-s3.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# 진우의 달 여행
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
direction = [-1, 0, 1]
|
||||
|
||||
grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
dp = [[[0]*3 for _ in range(m)] for _ in range(n)]
|
||||
|
||||
for i in range(m):
|
||||
for j in range(len(direction)):
|
||||
dp[0][i][j] = grid[0][i]
|
||||
|
||||
for i in range(1, n):
|
||||
for j in range(m):
|
||||
for k in range(len(direction)):
|
||||
if j == 0:
|
||||
dp[i][j][k] = min([dp[i-1][j+direction[h]][h] for h in range(len(direction)) if h != k and direction[h] != -1]) + grid[i][j]
|
||||
elif j == m-1:
|
||||
dp[i][j][k] = min([dp[i-1][j+direction[h]][h] for h in range(len(direction)) if h != k and direction[h] != 1]) + grid[i][j]
|
||||
else:
|
||||
dp[i][j][k] = min([dp[i-1][j+direction[h]][h] for h in range(len(direction)) if h != k]) + grid[i][j]
|
||||
|
||||
print(min([min(dp[n-1][j]) for j in range(m)]))
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
"""
|
||||
풀이(2) -> dp
|
||||
|
||||
걸린 시간: 45분
|
||||
|
||||
시간 복잡도: n*m*3(방향)으로 된 3차원 dp를 채우는데, 방향을 채울 때 본인을 제외한 방향들의 최소를 구하기 때문에 *2를 해서 (n*m*3*2)이다.
|
||||
|
||||
|
||||
해설: 다른 풀이에서 DP가 있다는 것을 알게되어서 두 번째 풀이를 진행했다.
|
||||
i, j, k는 행, 열, 이전 방향이라고 할때, dp[i][j][k]를 구하면 i-1번째 행에서 direction[k]방향을 제외한 j열의 값들 중에 최소와
|
||||
현재 행렬 값(grid[i][j])의 합이다.
|
||||
즉 [i][j][0]은 direction[0]이 -1방향이므로 [i-1][j-1]에서 값을 가져오는데 [i-1][j-1][0]을 제외한 값들 중에 최소를 가져온다.
|
||||
"""
|
||||
|
||||
"""
|
||||
풀이(1) -> dfs
|
||||
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: 첫 행에서 갈 수 있는 경우의 수는 3이고 마지막 행을 제외한 행에서 경우의 수는 2이므로 3*2^(n-2) 이다.
|
||||
이것을 열 개수만큼 반복해야 하므로 3*2^(n-2)*m 이다. 사실상 O(2^n * m)이라서 말이 안되는 시간복잡도이지만 조건때문에 그냥 했다.
|
||||
|
||||
해설: 2 <= n, m <= 6인걸 봐서는 모든 경우의 수를 확인해보라는 것 같다. (3 * 2^4) * 6 개이므로 얼마 안된다.
|
||||
dfs의 기저를 depth가 n-1보다 클때, 즉 마지막 행에 도달했을 때로 잡았고, 지금까지 더해온 total에 마지막 grid 값을 더한 뒤
|
||||
result 리스트에 넣고 마지막에 min을 구해서 출력하도록 하였다.
|
||||
이전에 어디로 갔는지도 계속 가져가며 갈 수 있는 전체 방향에서 이전에 간 방향 빼고, 열 밖으로 나가는 것까지 빼면 된다.
|
||||
total을 어떻게 계속 갱신할지 dfs에 선언하면 꼬일 것 같아서 고민했는데 그냥 인자로만 계속 넘기면 괜찮은 것 같다.
|
||||
|
||||
"""
|
||||
|
||||
# result = []
|
||||
|
||||
# def solution():
|
||||
# n, m = map(int, input().rstrip().split())
|
||||
|
||||
# grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
# dx = [-1, 0, 1]
|
||||
# dy = [1, 1, 1]
|
||||
|
||||
# def dfs(depth, col, before, total):
|
||||
# if depth >= n-1:
|
||||
# total += grid[depth][col]
|
||||
# result.append(total)
|
||||
# return
|
||||
|
||||
# for i in range(3):
|
||||
# if i == before or col+dx[i] >= m or col+dx[i] < 0:
|
||||
# continue
|
||||
# dfs(depth+dy[i], col+dx[i], i, total+grid[depth][col])
|
||||
|
||||
|
||||
# return total
|
||||
|
||||
# for i in range(m):
|
||||
# dfs(0, i, -1, 0)
|
||||
|
||||
|
||||
# print(min(result))
|
||||
# return
|
||||
|
||||
|
||||
# solution()
|
||||
51
workbook_8708/silver/17615-s1.py
Normal file
51
workbook_8708/silver/17615-s1.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# 볼 모으기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def count_result(n, balls, left, right, ball_count):
|
||||
left_count, right_count = 0, 0
|
||||
left_idx, right_idx = 0, n-1
|
||||
while left_idx <= n-1 and balls[left_idx] == left:
|
||||
left_count += 1
|
||||
left_idx += 1
|
||||
|
||||
while right_idx >= 0 and balls[right_idx] == right:
|
||||
right_count += 1
|
||||
right_idx -= 1
|
||||
|
||||
return min(ball_count[left]-left_count, ball_count[right]-right_count)
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
balls = list(input().rstrip())
|
||||
|
||||
ball_count = {"R": 0, "B": 0}
|
||||
|
||||
for b in balls:
|
||||
ball_count[b] += 1
|
||||
|
||||
result = min(count_result(n, balls, "R", "B", ball_count), count_result(n, balls, "B", "R", ball_count))
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분
|
||||
|
||||
시간 복잡도: count_result가 왼쪽, 오른쪽에 대해 첫 묶음이 몇 개인지 계산하는데 최악의 경우 전체이므로,
|
||||
O(n)이다. 처음에 ball_count를 셀 때 O(n)이고, count_result가 2번이므로 O(3n), 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 같은 것끼리 묶인 최종 상태는 한쪽 끝이 B, R 하나씩 있어야 된다.
|
||||
따라서 큰 경우의 수는 양 끝이 R, B 이거나 B, R인 경우이다.
|
||||
이제 각 경우의 수마다 R을 넘길지 B를 넘길지 계산하면 되는데,
|
||||
정해진 경우의 끝에 따라서 같은 묶음만 뺀 개수를 세면 된다.
|
||||
경우의 수 1) R, B일때 왼쪽 R 묶음 제거한 R 개수, 오른쪽 B 묶음 제거한 B개수 중 최소
|
||||
경우의 수 2) B, R일때 왼쪽 B 묶음 제거한 B 개수, 오른쪽 R 묶음 제거한 R개수 중 최소
|
||||
두 경우의 수 중 최소 값 구하면 된다.
|
||||
"""
|
||||
35
workbook_8708/silver/1927-s2.py
Normal file
35
workbook_8708/silver/1927-s2.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# 최소 힙
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
h = []
|
||||
|
||||
for i in range(n):
|
||||
v = int(input().rstrip())
|
||||
if v == 0:
|
||||
if len(h) == 0:
|
||||
print(0)
|
||||
continue
|
||||
print(heapq.heappop(h))
|
||||
else:
|
||||
heapq.heappush(h, v)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 5분
|
||||
|
||||
시간 복잡도: heappush와 heappop 모두 현재 트리의 높이 즉, logn만큼 든다.
|
||||
트리 길이가 점점 길어져서 n까지 가는 것이기 때문에 평균적으로 O(logn)이다.
|
||||
n번 진행하기 때문에 전체 시간복잡도는 O(nlogn)이다.
|
||||
|
||||
해설: 대놓고 힙 써서 구현하라고 해서 쉬웠다.
|
||||
0일때 pop하는데, 배열 길이가 0이면 0 출력하도록 설정
|
||||
넣을때는 heappush, 뺄때는 heappop 하면 끝
|
||||
"""
|
||||
58
workbook_8708/silver/19637-s3.py
Normal file
58
workbook_8708/silver/19637-s3.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# IF문 좀 대신 써줘
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def binary_search(target, badge):
|
||||
l, r = 0, len(badge)
|
||||
|
||||
while l < r:
|
||||
mid = (l+r)//2
|
||||
if badge[mid][1] >= target:
|
||||
r = mid
|
||||
else:
|
||||
l = mid + 1
|
||||
return l
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
badge = []
|
||||
name, value = input().rstrip().split()
|
||||
badge.append((name, int(value)))
|
||||
for i in range(n-1):
|
||||
name, value = input().rstrip().split()
|
||||
if badge[-1][1] == int(value):
|
||||
continue
|
||||
badge.append((name, int(value)))
|
||||
|
||||
for i in range(m):
|
||||
target = int(input().rstrip())
|
||||
idx = binary_search(target, badge)
|
||||
print(badge[idx][0])
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: m개의 값에 대해 n범위에서 이분탐색을 진행하기 때문에 O(mlogn)
|
||||
|
||||
해설: 문제가 너무 단순해서 뭔가 했는데 n, m <= 10^5 이기 때문에 n에서 비교를 최대한 줄이는 것이 핵심이다.
|
||||
n으로 만들어진 수직선 상에 m이 들어갈 위치를 찾으면 되기 때문에 이분탐색으로 진행한다.
|
||||
10^5는 17정도에서 끝낼 수 있다. badge에 상한 값이 겹치는 애들은 첫번째만 넣고, m개 받으면서 이분탐색 진행
|
||||
|
||||
이분탐색 정리했는데 자꾸 헷갈리니까 다시 정리
|
||||
내가 찾고자 하는건 badge의 idx이다. 즉 mid 기준으로 생각하는게 편하다.
|
||||
지금 문제는 target이 어느 상한에 속하나인데, 100이라면 100이상의 상한을 찾아서 가장 먼저 나오는
|
||||
상한값이 답인 것이다. 따라서 badge[mid][1] >= target으로 기본을 잡으면 되고,
|
||||
저게 성립하면 mid는 답이 될 수 있지만 왼쪽에 답이 있을 수도 있다.
|
||||
따라서 r을 움직여야하고, 현재 mid를 포함한 값이 되야 한다. r = mid
|
||||
반대 상황은 badge가 target보다 작은거니까 현재 mid가 답이 될 수 없으므로 l = mid + 1
|
||||
원소의 유무 판단이 아닌 들어갈 곳 찾기기 때문에 l, r = 0, len(badge)로 한다.
|
||||
while문 기본 조건은 들어갈 자리를 찾는 것이기 때문에 l = r일때는 알아보는 것이 의미 없다. 따라서 while l < r
|
||||
끝.
|
||||
"""
|
||||
78
workbook_8708/silver/19941-s3.py
Normal file
78
workbook_8708/silver/19941-s3.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# 햄버거 분배
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def clear_left(d, i, k):
|
||||
while len(d) >= 1 and d[0][0] < i - (k):
|
||||
d.popleft()
|
||||
return
|
||||
|
||||
def clear_right(d, i, k):
|
||||
while len(d) >= 1 and d[-1][0] < i - (k):
|
||||
d.pop()
|
||||
return
|
||||
|
||||
def manage_h(d, i, t, result):
|
||||
if len(d) >= 1 and d[-1][1] == "P":
|
||||
d.pop()
|
||||
result += 1
|
||||
else:
|
||||
d.append((i, t))
|
||||
return result
|
||||
|
||||
def manage_p(d, i, t, result):
|
||||
if len(d) >= 1 and d[0][1] == "H":
|
||||
d.popleft()
|
||||
result += 1
|
||||
else:
|
||||
d.appendleft((i, t))
|
||||
return result
|
||||
|
||||
MANAGEMENT = {
|
||||
"H": manage_h,
|
||||
"P": manage_p
|
||||
}
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
|
||||
table = input().rstrip()
|
||||
|
||||
d = deque()
|
||||
|
||||
result = 0
|
||||
for i, t in enumerate(table):
|
||||
clear_left(d, i, k)
|
||||
clear_right(d, i, k)
|
||||
manager = MANAGEMENT.get(t, None)
|
||||
|
||||
if not manager:
|
||||
return -1
|
||||
|
||||
result = manager(d, i, t, result)
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: deque의 길이를 k로 유지하면서 테이블에 있는 하나의 요소는 deque에 1번만 들어오거나 나가기 때문에
|
||||
한 요소 당 시간 복잡도는 O(1)이고 전체 요소에 대해서 진행하기 때문에 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: P, H가 짝을 지어서 사라지면 된다고 생각하여 스택을 떠올렸고, 오래된 H나 P는 선택할 수 없게 지워버리는 방법을 생각했을 때
|
||||
큐가 생각나서, 합쳐서 deque를 사용하기로 하였다.
|
||||
처음에는 오래된 것들을 나가는 방향을 popleft, P/H가 들어오는 곳은 append, 짝을 이뤄서 나가는 방향을 pop으로 생각했는데,
|
||||
이러면 과거 H를 P가 먹을 수 있는 상황에서 가장 최신 H만 먹기 때문에 최선이 아니다.
|
||||
따라서 P는 들어오는 것과 짝 맞춰서 나가는 것을 왼쪽, H는 오른쪽으로 함으로써 우선순위를 오래 기다린 사람과 오래된 햄버거로 하였다.
|
||||
그리고 이번에 들어오는 요소는 k 범위 이전 것들과는 전혀 상호작용할 수 없으므로 매번 clear를 왼쪽, 오른쪽을 다 해준다.
|
||||
|
||||
참고: len(list, deque, set, dict)들 모두 원소의 개수를 따로 저장하고 있기 때문에 O(1)이다.
|
||||
"""
|
||||
47
workbook_8708/silver/20006-s2.py
Normal file
47
workbook_8708/silver/20006-s2.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# 랭킹전 대기열
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
p, m = map(int, input().rstrip().split())
|
||||
|
||||
room = {}
|
||||
for i in range(p):
|
||||
l, n = input().rstrip().split()
|
||||
l = int(l)
|
||||
for j in room:
|
||||
if len(room[j]) < m and l >= j[0]-10 and l <= j[0]+10:
|
||||
room[j].append((l, n))
|
||||
break
|
||||
else:
|
||||
room[(l, n)] = [(l, n)]
|
||||
|
||||
for v in room.values():
|
||||
if len(v) == m:
|
||||
print("Started!")
|
||||
else:
|
||||
print("Waiting!")
|
||||
for j in sorted(v, key=lambda x: x[1]):
|
||||
print(*j)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분
|
||||
|
||||
시간 복잡도: p개의 플레이어를 방에 분배하기 위해 각 방을 확인해보는 시간 복잡도도 균등분배 기준으로 p//m개 방이므로, O(p* p//m) = O(p^2*m)이다.
|
||||
room.values()를 확인하며 정렬하고 출력하는 것은 p//m 즉 균등분배 가정으로 나올 수 있는 최대 방 개수만큼 정렬하기 때문에
|
||||
O(mlogm * p//m)이므로 O(plogm)이다.
|
||||
따라서 전체 시간 복잡도는 O(p^2*m)이다.
|
||||
p, m <= 300이기 때문에 그냥했지만 크기가 커진다면 모르기 때문에 들어갈 방을 범위로 나타내서 이분탐색을 하면 줄일 수 있다.
|
||||
물론 방이 다 차면 같은 범위를 가지는 방이 또 필요할 수 있기 때문에 적절히 조치를 취해야한다.
|
||||
|
||||
해설: p개의 플레이어를 확인하면서 맞는 room이 있다면 넣고, 없다면 room을 만든다. 이때, 딕셔너리를 사용했는데 level만 키로 쓰면 중복될 수 있으므로,
|
||||
(level, name)을 키로 써서 해야한다. 플레이어마다 생성된 room을 순서대로 다 범위를 확인한다. (이분 탐색을 쓰면 더 좋겠다.)
|
||||
다 room에 넣은 후 room 길이에 따라 started와 waiting을 쓰고, 이름 순으로 정렬한 뒤 출력한다.
|
||||
"""
|
||||
72
workbook_8708/silver/20125-s4.py
Normal file
72
workbook_8708/silver/20125-s4.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# 쿠키의 신체 측정
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def find_heart(grid, n, k):
|
||||
for i in range(n):
|
||||
if grid[k][i] == "*":
|
||||
return [k+1, i]
|
||||
else:
|
||||
return [-1, -1]
|
||||
|
||||
def down_check_star(grid, n, x, y):
|
||||
length = 0
|
||||
while x <= n-1:
|
||||
if grid[x][y] != "*":
|
||||
break
|
||||
length += 1
|
||||
x += 1
|
||||
return length
|
||||
|
||||
def row_check_star(grid, n, x, y, dir): # 오른쪽 +1, 왼쪽 -1
|
||||
length = 0
|
||||
while y <= n-1 and y >= 0:
|
||||
if grid[x][y] != "*":
|
||||
break
|
||||
length += 1
|
||||
y += dir
|
||||
return length
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
grid = []
|
||||
heart = [-1, -1]
|
||||
left_arm = 0
|
||||
right_arm = 0
|
||||
mid = 0
|
||||
left_leg = 0
|
||||
right_leg = 0
|
||||
for i in range(n):
|
||||
grid.append(input().rstrip())
|
||||
if heart[0] == -1:
|
||||
heart = find_heart(grid, n, i)
|
||||
|
||||
left_arm = row_check_star(grid, n, heart[0], heart[1]-1, -1)
|
||||
right_arm = row_check_star(grid, n, heart[0], heart[1]+1, +1)
|
||||
mid = down_check_star(grid, n, heart[0]+1, heart[1])
|
||||
left_leg = down_check_star(grid, n, heart[0]+mid+1, heart[1]-1)
|
||||
right_leg = down_check_star(grid, n, heart[0]+mid+1, heart[1]+1)
|
||||
|
||||
heart[0] += 1
|
||||
heart[1] += 1
|
||||
print(*heart)
|
||||
print(left_arm, right_arm, mid, left_leg, right_leg)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: 팔, 다리, 허리는 일자로 있기 때문에 O(n)이지만, 머리는 (0,0) 부터 쭉 찾아서 처음 나오는
|
||||
*이므로 O(n^2)이다. 따라서 전체 시간 복잡도는 O(n^2)이다.
|
||||
|
||||
해설: (0,0)에서 선형으로 찾다가 가장 먼저 나오는 *이 머리이다. 이 머리 바로 한 칸 밑이 심장이다.
|
||||
심장에서 팔, 다리, 허리를 구하면 되는데, 연속된 *을 찾는 것이다.
|
||||
이는 행으로 연속된 별 찾기와 열로 연속된 별 찾기 함수 2개를 만들어서 진행하면 된다.
|
||||
위로 올라갈 일은 없어서 열은 그냥 down으로 했고, 행은 row로 방향을 인자로 받아서 체크했다.
|
||||
"""
|
||||
61
workbook_8708/silver/20310-s3.py
Normal file
61
workbook_8708/silver/20310-s3.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# 타노스
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
|
||||
s_dict = {"0": [], "1": []}
|
||||
len_0 = 0
|
||||
len_1 = 0
|
||||
|
||||
for i in range(len(s)):
|
||||
if s[i] == "0":
|
||||
s_dict["0"].append(i)
|
||||
len_0 += 1
|
||||
else:
|
||||
s_dict["1"].append(i)
|
||||
len_1 += 1
|
||||
|
||||
len_0 //= 2
|
||||
len_1 //= 2
|
||||
|
||||
s_dict["0"] = deque(s_dict["0"][:len_0])
|
||||
s_dict["1"] = deque(s_dict["1"][len_1:])
|
||||
|
||||
new_s = ""
|
||||
|
||||
for _ in range(len_0+len_1):
|
||||
idx_0 = s_dict["0"][0] if len_0 > 0 else float('inf')
|
||||
idx_1 = s_dict["1"][0] if len_1 > 0 else float('inf')
|
||||
if idx_0 > idx_1:
|
||||
s_dict["1"].popleft()
|
||||
len_1 -= 1
|
||||
new_s += "1"
|
||||
else:
|
||||
s_dict["0"].popleft()
|
||||
len_0 -= 1
|
||||
new_s += "0"
|
||||
|
||||
|
||||
print(new_s)
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: s길이만큼 개수를 세고, s길이의 반만큼 재배열을 하기 때문에 O(len(s))이다. 그런데 나처럼 popleft 하면서 하지 않고,
|
||||
그냥 두 리스트 합친다음에 sort하면 nlogn이므로 내가 더 낫다.
|
||||
|
||||
해설: 새로운 문자열 s는 기존 s에서 재배열 하는 것이 아니라 그냥 빼는 것이었다. 문제 설명 개별로네..
|
||||
아무튼 그래서 개수를 세고 1은 앞에 있는 것부터 반만큼 지우고, 0은 뒤에 있는 것부터 반만큼 지우면 된다.
|
||||
그렇게 하기 위해서 0과 1의 인덱스를 따로 기록해두고 0의 인덱스 리스트는 앞에서부터 반 자르고, 1은 반부터 뒤까지 자른다.
|
||||
마지막으로 이 인덱스 리스트 2개를 맨 앞에 것들끼리 비교해서 작은 놈을 popleft 하고, 그에 맞는 숫자(0 또는 1)을 new_s에 추가한다.
|
||||
deque는 슬라이스를 지원하지 않아서, 리스트에서 슬라이스하고 popleft 하기 전에 deque로 만들었다.
|
||||
"""
|
||||
55
workbook_8708/silver/2075-s3.py
Normal file
55
workbook_8708/silver/2075-s3.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# N번째 큰 수
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
rank = list(map(int, input().rstrip().split()))
|
||||
heapq.heapify(rank)
|
||||
for _ in range(n-1):
|
||||
nums = list(map(int, input().rstrip().split()))
|
||||
for i in range(n):
|
||||
heapq.heappush(rank, nums[i])
|
||||
heapq.heappop(rank)
|
||||
|
||||
print(heapq.heappop(rank))
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분(메모리 때문에 고민 좀 했다.)
|
||||
|
||||
시간 복잡도: O(n^2logn) n^2개의 수를 읽을때마다 n개 길이의 힙에서 push와 pop을 하기 때문에 정렬 하는 것까지 logn해서 O(n^2logn)이다.
|
||||
|
||||
해설: 첫 번째 코드는 맨 마지막 행부터 n개중에 1등을 뽑고 1등이 나온 열에서 바로 한칸 위에 애를 데리고 또 n개중에 1등을 뽑고 총 n번을 진행하려고 했다.
|
||||
그런데 결국 이게 O(n^2)이라는 것을 깨닫고 여기서 n개 중에 1등을 뽑는 방식을 줄이기 위해 heap을 생각해냈다. 그러면 1등 뽑을 때 O(logn)에 할 수 있다.
|
||||
다른 문제가 하나 있는데 메모리 제한이 12MB라서 처음에 n^2개의 수들을 리스트에 저장하지 말고 한 줄씩 읽는대로 처리해야했다.
|
||||
따라서 한 줄씩 heap에 넣으며 1등만 데리고 다음 줄로 넘어가서 확인하는 방식으로 하려고 했는데 이건 마지막 라인에서 경합 자격도 없는 애가 승부를
|
||||
벌이게 되는 논리적 모순이 생기기 때문에 그냥 하나씩 계속 읽으면서 길이 n을 유지하는 최소 힙에 넣고 마지막에 heappop 하면 된다.
|
||||
"""
|
||||
|
||||
# def solution():
|
||||
# n = int(input().rstrip())
|
||||
|
||||
# nums = [[] for _ in range(n)]
|
||||
# for _ in range(n):
|
||||
# row = input().rstrip().split()
|
||||
# for i in range(n):
|
||||
# nums[i].append(int(row[i]))
|
||||
|
||||
# rank = [(-nums[i].pop(), i) for i in range(n)]
|
||||
# heapq.heapify(rank)
|
||||
|
||||
# for i in range(n-1):
|
||||
# _, nums_idx = heapq.heappop(rank)
|
||||
# heapq.heappush(rank, (-nums[nums_idx].pop(), nums_idx))
|
||||
|
||||
# print(-heapq.heappop(rank)[0])
|
||||
|
||||
# return
|
||||
59
workbook_8708/silver/20920-s3.py
Normal file
59
workbook_8708/silver/20920-s3.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# 영단어 암기는 괴로워
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def set_priority(words, word):
|
||||
word_info = words.get(word, None)
|
||||
frequency, length = 0, 0
|
||||
if word_info:
|
||||
frequency = -(word_info[0]) + 1
|
||||
length = -(word_info[1])
|
||||
else:
|
||||
frequency = 1
|
||||
length = len(word)
|
||||
|
||||
words[word] = [-frequency, -length, word, 0]
|
||||
return words[word]
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
words = {}
|
||||
|
||||
word_list = []
|
||||
|
||||
for i in range(n):
|
||||
word = input().rstrip()
|
||||
|
||||
if len(word) < m:
|
||||
continue
|
||||
|
||||
heapq.heappush(word_list, set_priority(words, word))
|
||||
|
||||
for i in range(len(word_list)):
|
||||
f, l, w, is_pop = heapq.heappop(word_list)
|
||||
if words.get(w)[3]:
|
||||
continue
|
||||
else:
|
||||
print(w)
|
||||
words[w][3] = 1
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: set_priority는 단어 길이를 세고, 정보를 dict에서 읽고 쓰는 것인데 m은 최대 10이므로 전체 시간복잡도는 O(1)이다.
|
||||
solution 함수에서 n개의 단어를 보며 set_priority를 실행하고, heap에 push하므로 요소당 O(logn)이기 때문에 O(nlogn)이다.
|
||||
마지막으로 word_list를 확인할 때도 heap에서 pop이므로 O(nlogn)이다. 따라서 전체 시간복잡도는 O(nlogn)이다.
|
||||
|
||||
해설: heap에서 정렬할 때 우선순위 3가지로 정렬하도록 리스트를 넣는다.
|
||||
그러기 위해 word_info dict을 만들어서 정보 업데이트를 O(1)에 한다.
|
||||
단어마다 정보를 업데이트 해가며 heap에 넣고, 다 넣은 다음 heappop 하면서 기존에 안 나온 것들만 출력을 한다.
|
||||
좀 빠르게 해보겠다고 heap 써서 O(nlogn)으로 했지만 그냥 Counter 하고, 우선순위 역순으로 sort 3번 하면 이것도 O(nlogn)이다...
|
||||
"""
|
||||
44
workbook_8708/silver/20922-s1.py
Normal file
44
workbook_8708/silver/20922-s1.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# 겹치는 건 싫어
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
s = list(map(int, input().rstrip().split()))
|
||||
|
||||
idx = 0
|
||||
c = {}
|
||||
d = deque([])
|
||||
result = 0
|
||||
while idx < len(s):
|
||||
new = s[idx]
|
||||
if not c.get(new, 0):
|
||||
c[new] = 0
|
||||
d.append(new)
|
||||
c[new] += 1
|
||||
if c[new] > k:
|
||||
while d and c[new] > k:
|
||||
now = d.popleft()
|
||||
c[now] -= 1
|
||||
result = max(result, len(d))
|
||||
idx += 1
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 15분
|
||||
|
||||
시간 복잡도: 한 요소가 deque에 들어갔다가 나오기를 한번씩만 하므로 O(n)이다.
|
||||
|
||||
해설: deque에 숫자를 넣고, 숫자마다 개수를 dict로 센다.
|
||||
숫자를 deque에 넣었을 때 그 숫자의 개수가 k개를 넘으면 그 숫자가 k개 이하가 될때까지 deque에서 popleft를 한다.
|
||||
매번 현재 길이를 최대 길이와 비교해간다.
|
||||
"""
|
||||
38
workbook_8708/silver/2164-s4.py
Normal file
38
workbook_8708/silver/2164-s4.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 카드2
|
||||
|
||||
import sys
|
||||
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
cards = deque([i for i in range(1, n+1)])
|
||||
|
||||
drop_count = 0
|
||||
while drop_count < n-1:
|
||||
cards.popleft()
|
||||
drop_count += 1
|
||||
cards.append(cards.popleft())
|
||||
|
||||
print(cards.pop())
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 13분
|
||||
|
||||
시간 복잡도: deque에 넣고 빼는 작업은 O(1)이므로, 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: deque에 넣고 진행할 경우 앞, 뒤에 대한 추가, 삭제 연산이 O(1)이므로 이 자료구조를 활용해서 상황을 그대로 구현하면 된다.
|
||||
|
||||
규칙을 좀 찾아보면 먼저 홀수를 다 버리고, 짝수만 남은 상태에서 또 지워나가는 규칙을 찾을 수 있어서 수학적으로 풀 수 있을 것 같지만,
|
||||
이 문제를 서비스 자체라고 생각하면 조건이 어떻게 바뀔지 모르는 상태에서 규칙을 찾아서 그 규칙에만 맞는 코드를 짜는 것보다는
|
||||
시뮬레이션쪽으로 설계함으로써 사람이 하기 힘든 반복 작업을 자동화하는 것이 더 목적성이 맞다고 생각한다.
|
||||
"""
|
||||
46
workbook_8708/silver/21921-s3.py
Normal file
46
workbook_8708/silver/21921-s3.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# 블로그
|
||||
|
||||
import sys
|
||||
|
||||
from collections import deque, Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, x = map(int, input().rstrip().split())
|
||||
|
||||
one_days = list(map(int, input().rstrip().split()))
|
||||
duration = deque([one_days[i] for i in range(x)])
|
||||
|
||||
duration_result = [0] * n
|
||||
duration_result[x-1] = sum(duration)
|
||||
|
||||
for i in range(x, n):
|
||||
before = duration.popleft()
|
||||
duration.append(one_days[i])
|
||||
after = duration[-1]
|
||||
duration_result[i] = duration_result[i-1] - before + after
|
||||
|
||||
c = Counter(duration_result)
|
||||
max_vistor = max(c)
|
||||
if max_vistor == 0:
|
||||
print('SAD')
|
||||
else:
|
||||
print(max_vistor)
|
||||
print(c.get(max_vistor))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 19분
|
||||
|
||||
시간 복잡도: 전체 요소를 한, 두바퀴 정도 돌기 때문에 O(n)이다.
|
||||
|
||||
해설: 그냥 인덱스로 앞 뒤로 줄이고, 늘이면 되는데 슬라이딩 윈도우는 deque를 쓰는게 좀 직관적이라서 deque를 사용했다.
|
||||
최대값과 count를 계속 업데이트 하는 것이 코드가 가독성이 떨어지는 것 같아서 어차피 그렇게 연산하는 것과
|
||||
마지막에 결과 리스트 한 바퀴 돌면서 개수 세는 연산이 비슷하기 때문에 그냥 결과 리스트에 쭉 저장하고 Counter로 개수를 셌다.
|
||||
0이 최대일 경우 SAD 출력(처음에 이거 안해서 틀림), 아니면 최대값과 그 개수를 출력한다.
|
||||
"""
|
||||
38
workbook_8708/silver/22233-s3.py
Normal file
38
workbook_8708/silver/22233-s3.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 가희와 키워드
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
memo = set()
|
||||
|
||||
for _ in range(n):
|
||||
memo.add(input().rstrip())
|
||||
|
||||
for _ in range(m):
|
||||
for keyword in input().rstrip().split(","):
|
||||
if keyword in memo:
|
||||
memo.remove(keyword)
|
||||
|
||||
print(len(memo))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 20분
|
||||
|
||||
시간 복잡도: 한 글에 최대 키워드가 10개이므로, set으로 차집합을 구하면 두 집합 중 작은 것만큼 시간이 드는데,
|
||||
작은 것의 최대 길이가 10이므로 O(10m)이다. set의 길이는 key의 개수이므로 O(1)이기 때문이다.
|
||||
|
||||
해설: 처음에는 memo - keyswords를 했는데 이 연산은 비파괴 연산이라 기존 set들을 유지해야하므로
|
||||
차집합된 set을 새로 만든다. 따라서 memo 길이만큼의 시간이 든다.
|
||||
그래서 in으로 있는지 확인(O(1))하고, remove(O(1))로 지웠다.
|
||||
remove는 key가 없으면 keyerror가 나는데 그래서 나는 있을 때만 지워서 괜찮았고,
|
||||
discard를 쓰면 있으면 지우고 없으면 그냥 가만히 있는다고 한다.
|
||||
"""
|
||||
59
workbook_8708/silver/2304-s2.py
Normal file
59
workbook_8708/silver/2304-s2.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# 창고 다각형
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
line = sorted([tuple(map(int, input().rstrip().split())) for _ in range(n)])
|
||||
|
||||
high_stack = []
|
||||
result = 0
|
||||
|
||||
for x, y in line:
|
||||
if not high_stack:
|
||||
high_stack.append((x, y))
|
||||
continue
|
||||
|
||||
last_pop = ()
|
||||
while len(high_stack) != 0 and high_stack[-1][1] <= y:
|
||||
last_pop = high_stack.pop()
|
||||
|
||||
if len(high_stack) == 0:
|
||||
result += (x - last_pop[0])*last_pop[1]
|
||||
|
||||
high_stack.append((x, y))
|
||||
|
||||
for _ in range(len(high_stack)):
|
||||
x, y = high_stack.pop()
|
||||
if len(high_stack) == 0:
|
||||
result += y
|
||||
else:
|
||||
result += (x - high_stack[-1][0])*y
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: while문이 있지만 어차피 전체적으로는 요소 기준으로 봤을 때 stack에 들어가고 나오는거 한번씩이기 때문에 O(n)이다.
|
||||
|
||||
해설: 가장 높은 놈(top)을 만날때까지는 그냥 max 갱신해가며 하면 되지만 내리막에서는 작은 놈을 갱신하며 가야된다.
|
||||
근데 내려갈때 무지성으로 작은 놈만 갱신해가면, 갑자기 큰 놈이 나왔을 때 우물형태가 생기므로 조건에 위배되기 때문에 지금까지 구했던것을 다시 계산해야된다.
|
||||
근데 그러면 돌아가서 다시 계산하기 때문에 O(n^2)이 되버린다.
|
||||
따라서 작은 놈을 계속 가져가되, 그것보다 큰 놈이 나왔을 때 이전 작은 것들을 버리는 방식으로 하면 된다. 이건 stack을 쓰면 쉽게 구현이 가능하다.
|
||||
따라서 스택에 넣는 조건을 내가 들어갈때 스택에(이전 놈들) 나보다 작은 애들은 다 pop하고 들어간다. 그렇게 끝에는 top과 완벽한 내리막만 남는다.
|
||||
이제 stack에서 pop을 하면서 pop한 녀석과 아직 stack에 남아있는 놈과의 거리로 넓이를 계산하고 마지막에 나오는 녀석은 너비가 1이므로 계산하면 된다.
|
||||
한 가지 문제는 오르막에서도 이 조건을 그대로 쓰면 나보다 작은 이전 놈들의 권리가 없어진다.
|
||||
따라서 내가 스택에 들어갈 때 나보다 작은 놈들을 다 pop했는데 stack이 비어 있다면 아직 top이 없었던 것이기 때문에 마지막에 나온 애는 넓이를 계산해준다.
|
||||
|
||||
다른 풀이로는 가장 높은 놈을 기준으로 오르막과 내리막이 나올 수밖에 없으므로, 왼쪽에서 top까지 max를 갱신해가며 넓이 구하고,
|
||||
오른쪽에서 top까지 반대로 가면서 max 갱신해가며 넓이 구해서 더하면 끝이긴 하네.
|
||||
"""
|
||||
56
workbook_8708/silver/2512-s2.py
Normal file
56
workbook_8708/silver/2512-s2.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# 예산
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
req = list(map(int, input().rstrip().split()))
|
||||
|
||||
m = int(input().rstrip())
|
||||
|
||||
if sum(req) <= m:
|
||||
print(max(req))
|
||||
return
|
||||
|
||||
now_ceil = m // n
|
||||
now_asset = m
|
||||
sorted_req = sorted(req)
|
||||
idx = 0
|
||||
|
||||
while idx < n-1 and now_ceil >= sorted_req[idx]:
|
||||
now_asset -= sorted_req[idx]
|
||||
idx += 1
|
||||
now_ceil = now_asset // (n-idx)
|
||||
|
||||
print(now_ceil)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간 10분
|
||||
|
||||
시간 복잡도: 내 풀이는 정렬할 때 O(nlogn)이고, n개의 요청예산을 보기 때문에 O(n)이라서 전체 시간복잡도는 O(nlogn)이다.
|
||||
이분탐색 풀이의 경우는 0부터 max(req) 범위에서 찾기 때문에 log(max(req))이고, 매 mid마다 req 내용을 다 확인하므로
|
||||
O(nlog(max(req)))이다.
|
||||
문제에서는 req <= 10^5이고, n <= 10000이기 때문에 log로 치면 내가 더 빠르지만 이 조건이 바뀌는 것에 따라 달라질 것 같다.
|
||||
|
||||
해설: 요청 예산의 합이 m보다 작거나 같다면 그냥 다 주고 요청 예산 중 최대값을 출력하면 된다.
|
||||
근데 아니라면 두 가지 풀이 방법이 있다.
|
||||
먼저 내가 처음 푼 방식은 요청 예산들을 오름차순으로 정렬한 후 처음 상한액을 평균값으로 매긴다.
|
||||
그 다음 한 곳씩 예산을 나눠주는데 이때 상한액 이하의 곳들은 나눠주고 남은 예산으로 남은 곳의 수를 나눠서 다시 평균값을 상한액으로 바꾼다.
|
||||
이 과정을 반복하다가 현재 상한액보다 많은 곳을 요청한 곳이 있으면 앞으로 뒤에 있는 곳들도 요청한만큼 채워줄 수 없기 때문에
|
||||
이번 상한액이 답이다.
|
||||
|
||||
근데 이분탐색으로 푸는 방법이 있음.
|
||||
전체 요청 예산의 범위 중 상한액을 이분 탐색으로 찾아가는 것임.
|
||||
한 점을 찾는 것이기 때문에 l <= r 조건에서 [mid]를 설정하고, n개의 요청 예산을 설정한 mid 기준으로 다 분배해본 후,
|
||||
m 이하 중 최대값을 찾으면 된다.
|
||||
s를 그때그때 결과라고 하면, 오름차순 정렬에서 s가 m 이하인 경우를 찾는 것이기 때문에 s <= m 이면 답이 될 수 있고,
|
||||
오른쪽을 찾아봐야하기 때문에 l = mid라고 생각할 수 있지만, 이것은 들어갈 곳이 아닌 한 점을 찾는 것이기 때문에
|
||||
l <= r을 한 이상 안 끝날 수도 있다. 따라서 mid는 따로 기록해두고, l = mid + 1, r= mid - 1로 해가며 찾아야한다.
|
||||
"""
|
||||
40
workbook_8708/silver/2531-s1.py
Normal file
40
workbook_8708/silver/2531-s1.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 회전 초밥
|
||||
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, d, k, c = map(int, input().rstrip().split())
|
||||
|
||||
belt = [int(input().rstrip()) for _ in range(n)]
|
||||
double_belt = belt + belt
|
||||
|
||||
eat = Counter(belt[:k])
|
||||
eat.setdefault(c, 0)
|
||||
eat[c] += 1
|
||||
result = len(eat)
|
||||
for i in range(1, len(double_belt)-k+1):
|
||||
eat[double_belt[i-1]] -= 1
|
||||
if eat[double_belt[i-1]] == 0:
|
||||
del eat[double_belt[i-1]]
|
||||
eat.setdefault(double_belt[i+k-1], 0)
|
||||
eat[double_belt[i+k-1]] += 1
|
||||
result = max(result, len(eat))
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 24분
|
||||
|
||||
시간 복잡도: 2n 길이의 리스트를 1번 순회하고, 그 과정에서 처리는 dict로 O(1)이므로, 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 같은 두 리스트를 이어붙여서 원형을 만든 후 k 구간씩 슬라이딩하면서 다른 종류의 개수를 세면 된다.
|
||||
각 음식마다 있는 개수는 dict에 저장하고, key의 개수 세기로 O(1)에 종류 개수를 세기 때문에 value가 0이면 del로 key까지 없앤다.
|
||||
"""
|
||||
29
workbook_8708/silver/25757-s5.py
Normal file
29
workbook_8708/silver/25757-s5.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# 임스와 함께하는 미니게임
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
game_types = {"Y": 2, "F": 3, "O": 4}
|
||||
|
||||
def solution():
|
||||
q = list(input().rstrip().split())
|
||||
n, personnel = int(q[0]), game_types.get(q[1], 0)
|
||||
people = set()
|
||||
for _ in range(n):
|
||||
people.add(input().rstrip())
|
||||
result = len(people) // (personnel-1)
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 18분
|
||||
|
||||
시간 복잡도: 사람들 이름을 쭉 읽고, 쓰고, set() 개수 세는 것까지 n이므로 전체 시간복잡도는 O(n)
|
||||
|
||||
해설: 한 사람이 임스와 두 번 게임을 할 수는 없으므로 참여 명단을 중복을 제거하는 set()을 활용한다.
|
||||
그 후 임스 본인을 제외한 게임에 필요한 인원 수로 set() 길이를 나누면 몫이 임스가 할 수 있는 게임 수이다.
|
||||
"""
|
||||
63
workbook_8708/silver/2607-s2.py
Normal file
63
workbook_8708/silver/2607-s2.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# 비슷한 단어
|
||||
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_similar(now_word, target_c):
|
||||
target_c_copy = target_c.copy()
|
||||
now_word_left = []
|
||||
for c in now_word:
|
||||
if len(target_c_copy) < 1:
|
||||
break
|
||||
|
||||
if target_c_copy.get(c, -1) == -1:
|
||||
now_word_left.append(c)
|
||||
continue
|
||||
|
||||
target_c_copy[c] -= 1
|
||||
if target_c_copy[c] == 0:
|
||||
del target_c_copy[c]
|
||||
|
||||
len_target_left = sum(target_c_copy.values())
|
||||
result = 1 if len_target_left <= 1 and len(now_word_left) <= 1 else 0
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
result = 0
|
||||
target = input().rstrip()
|
||||
target_c = Counter(target)
|
||||
|
||||
for _ in range(n-1):
|
||||
now_word = input().rstrip()
|
||||
if len(now_word) >= len(target)+2:
|
||||
continue
|
||||
|
||||
result += check_similar(now_word, target_c)
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 32분
|
||||
|
||||
시간 복잡도: 단어 길이를 m이라고 하자. 중복 제거할 때는 둘 중 짧은 단어만큼 진행된다. -> O(m)
|
||||
target_c의 values 합 구하기 -> O(m)
|
||||
이 두 과정이 check_similar()이고, O(m)이다. 이제 이 과정을 n-1개의 단어만큼 진행하기 때문에 전체 시간복잡도는 O(nm)이다.
|
||||
|
||||
해설: 비슷한 단어의 조건을 수치적으로 정리하면 target과 비교하는 단어의 길이 차이가 2이상 나면 안되고,
|
||||
겹치는 글자들을 개수 기준으로 다 제거했을 때 양쪽 다 남은 글자가 1을 초과하면 안된다.
|
||||
따라서 나는 target을 Counter로 만들고, 비교하는 단어를 쭉 보면서 target_c에 있으면 개수를 줄이는 방식으로 중복을 제거했다.
|
||||
이때 target_c에 없으면 남는 글자는 따로 리스트에 보관하였다.
|
||||
마지막으로 target_c의 values 합이 남는 글자 수고, len(lst)가 비교하는 글자의 남는 글자 수이므로 이것의 길이가 둘 다 <= 1일때만
|
||||
비슷한 단어로 판정했다.
|
||||
"""
|
||||
63
workbook_8708/silver/3758-s2.py
Normal file
63
workbook_8708/silver/3758-s2.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# KCPC
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def write_board(board, i, j, s, idx):
|
||||
if not board.get(i, 0):
|
||||
board[i] = {"problems": {}, "submit_count": 0, "last_submit": -1}
|
||||
|
||||
board[i]["problems"][j] = max(board[i]["problems"].get(j, 0), s)
|
||||
board[i]["submit_count"] += 1
|
||||
board[i]["last_submit"] = idx
|
||||
|
||||
return
|
||||
|
||||
def check_our_rank(board, t):
|
||||
ranking = []
|
||||
for k in board:
|
||||
info = (k, -sum(board[k]["problems"].values()), board[k]["submit_count"], board[k]["last_submit"])
|
||||
ranking.append(info)
|
||||
|
||||
ranking.sort(key=lambda x: (x[1], x[2], x[3]))
|
||||
|
||||
for i, record in enumerate(ranking):
|
||||
if record[0] == t:
|
||||
return i+1
|
||||
|
||||
def test(n ,k ,t, m):
|
||||
board = {} # 팀id: {문제: {번호: 점수}, 제출 횟수: ~, 마지막 제출 인덱스: ~}
|
||||
for idx in range(m):
|
||||
i, j, s = map(int, input().rstrip().split())
|
||||
write_board(board, i, j, s, idx)
|
||||
|
||||
return check_our_rank(board, t)
|
||||
|
||||
|
||||
|
||||
def solution():
|
||||
T = int(input().rstrip())
|
||||
for _ in range(T):
|
||||
n, k, t, m = map(int, input().rstrip().split())
|
||||
print(test(n, k, t, m))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: write_board가 O(1), check_our_rank가 sort때문에 O(nlogn)이므로, 이 둘을 활용한 test는 O(nlogn)이다.
|
||||
따라서 전체 시간복잡도는 test하는 횟수를 곱해서 O(Tnlogn)이다.
|
||||
|
||||
해설: 문제에서 시키는대로 구현하면 된다. 순위를 정하기 위해 마지막에 정렬해야 하는데 기준이 되는 요소들이
|
||||
최종 점수 > 제출 횟수 > 마지막 제출 시간이기 때문에 이 정보들을 dict에 기록하면서 진행하기로 했다.
|
||||
최종 점수를 계속 갱신하는 것이 신경쓸 것이 좀 있어서 마지막에 한번에 모아서 계산하는거랑 그때그때 갱신하는 거랑 시간복잡도는 같다고
|
||||
판단하여 마지막에 계산하였다.
|
||||
그 후 팀 id와 3가지 요소를 튜플로 묶어서 리스트에 넣은 다음 lambda를 활용하여 sort 하였다.
|
||||
동순위는 없으므로 팀 id가 t인 튜플의 인덱스+1을 한 것이 답이다.
|
||||
"""
|
||||
65
workbook_8708/silver/4659-s5.py
Normal file
65
workbook_8708/silver/4659-s5.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# 비밀번호 발음하기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
VOWEL = "aeiou"
|
||||
CONSONANT_OR_VOWEL = {a: 0 for a in alphabet} # 0이면 자음, 1이면 모음
|
||||
for v in VOWEL:
|
||||
CONSONANT_OR_VOWEL[v] = 1
|
||||
|
||||
def check_word(word):
|
||||
is_vowel_in = False
|
||||
sequence_count = [-1, 0] # sequence_count[0]은 자음(0),모음(1) 구분, sequence_count[1]은 count
|
||||
before_w = ""
|
||||
for w in word:
|
||||
if not is_vowel_in and CONSONANT_OR_VOWEL[w] == 1: # 1번째 조건
|
||||
is_vowel_in = True
|
||||
|
||||
if sequence_count[0] == CONSONANT_OR_VOWEL[w]: # 2번째 조건
|
||||
sequence_count[1] += 1
|
||||
if sequence_count[1] >= 3:
|
||||
return False
|
||||
else:
|
||||
sequence_count[0], sequence_count[1] = CONSONANT_OR_VOWEL[w], 1
|
||||
|
||||
if before_w not in ("e", "o") and before_w == w: # 3번째 조건
|
||||
return False
|
||||
before_w = w
|
||||
|
||||
if not is_vowel_in: # 1번째 조건 최종 확인
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def solution():
|
||||
while 1:
|
||||
word = input().rstrip()
|
||||
if word == "end":
|
||||
break
|
||||
|
||||
is_acceptable = check_word(word)
|
||||
|
||||
if is_acceptable:
|
||||
print(f"<{word}> is acceptable.")
|
||||
else:
|
||||
print(f"<{word}> is not acceptable.")
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: 들어오는 모든 단어의 길이만큼의 시간이 걸린다.
|
||||
|
||||
해설: 자음과 모음 여부를 dictionary에 1, 0으로 O(1)에 구분할 수 있도록 세팅을 해둔다.
|
||||
1번 조건은 한글자씩 볼 때 모음 여부에 따라 is_vowel_in 진위 여부를 결정한다.
|
||||
2번 조건은 어떤 것이 몇 번 연속되고 있는지 현황을 기록하는 길이 2 리스트를 만들어서 판단한다. 기록과 다른 것이 나오면 초기화한다.
|
||||
3번 조건은 이전 단어를 저장하는 변수를 만들고 이전 단어가 "e", "o"이면 통과하고, 아닐 경우 2번 연속되는지 확인한다.
|
||||
"""
|
||||
79
workbook_8708/silver/9017-s3.py
Normal file
79
workbook_8708/silver/9017-s3.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# 크로스 컨트리
|
||||
|
||||
import sys
|
||||
|
||||
from collections import Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def exclude_team(teams):
|
||||
excluded = set()
|
||||
|
||||
for team in teams:
|
||||
if teams[team] != 6:
|
||||
excluded.add(team)
|
||||
|
||||
return excluded
|
||||
|
||||
def find_winning_team(rank, excluded, team_count, n):
|
||||
team_score = {i: {"count": 0, "score": 0} for i in range(1, team_count+1) if i not in excluded}
|
||||
first_5th = {}
|
||||
now_rank = 0
|
||||
for r in rank:
|
||||
if r in excluded:
|
||||
continue
|
||||
|
||||
now_rank += 1
|
||||
|
||||
if team_score[r]["count"] >= 4:
|
||||
if first_5th.get(r, 0) == 0:
|
||||
first_5th[r] = now_rank
|
||||
continue
|
||||
team_score[r]["score"] += (now_rank)
|
||||
team_score[r]["count"] += 1
|
||||
|
||||
winner = {"team": 0, "score": float("inf"), "5th": n+1}
|
||||
for team in team_score:
|
||||
if team_score[team]["score"] < winner["score"]:
|
||||
winner["team"], winner["score"], winner["5th"] = team, team_score[team]["score"], first_5th.get(team, n+1)
|
||||
elif team_score[team]["score"] == winner["score"] and first_5th.get(team, n+1) < winner["5th"]:
|
||||
winner["team"], winner["score"], winner["5th"] = team, team_score[team]["score"], first_5th.get(team, n+1)
|
||||
else:
|
||||
continue
|
||||
|
||||
return winner["team"]
|
||||
|
||||
|
||||
def game():
|
||||
n = int(input().rstrip())
|
||||
rank = list(map(int, input().rstrip().split()))
|
||||
teams = Counter(rank)
|
||||
excluded = exclude_team(teams)
|
||||
|
||||
result = find_winning_team(rank, excluded, len(teams), n)
|
||||
|
||||
return result
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
for _ in range(t):
|
||||
result = game()
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분 정도(score를 반대로 생각하거나, dictionary keyerror 때문에..) -> dict는 앵간하면 .get()으로 하자.
|
||||
|
||||
시간 복잡도: exclude_team()은 Counter 객체 전체를 순회하기 때문에 O(m)이다.
|
||||
find_winning_team()은 rank 전체를 순회하고 팀 리스트를 순회하는 것인데 set과 dict를 쓰므로 O(1)이라서 전체는 m < n이므로 O(n)이다.
|
||||
game()은 Counter이므로 O(m)에다가 exclude_team()과 find_winning_team()을 돌리기 때문에 전체는 O(n)이다.
|
||||
마지막으로 전체 프로그램은 game()을 t번 반복하기 때문에 전체 시간복잡도는 O(t*n)이다.
|
||||
함수별로 나눠놓으니까 전체 시간복잡도를 계산하는 것이 확실히 편하다.
|
||||
|
||||
해설: 먼저 6명이 아닌 팀을 counter로 알아낸 뒤 제외한다. 그 후 rank 리스트를 순차적으로 확인하면서 팀의 총점을 기록한다.
|
||||
이때, 4등까지만 계산을 하도록 조건을 걸어주고, 팀의 5등이 전체 몇 등인지만 dict에 저장한다.
|
||||
마지막에 총점을 비교하고, 같다면 5등까지 확인하는 절차를 거쳐서 최종 우승 팀을 결정한다.
|
||||
"""
|
||||
38
workbook_8708/silver/9655-s5.py
Normal file
38
workbook_8708/silver/9655-s5.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 돌 게임
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
print("SK") if n%2 == 1 else print("CY")
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분(dp로도 풀 수 있을 것 같아서 고민하다가..)
|
||||
|
||||
시간 복잡도: 그냥 % 계산 한번이니까 O(1)이다.
|
||||
|
||||
해설: 마지막에 무조건 창영이가 가져가기 때문에 상근이가 이기려면 돌을 남겨두면 안된다.
|
||||
완벽하게 게임을 한다는 이야기는 서로 이기기 위해 최선을 다한 수만 생각한다.
|
||||
k번째에 경기가 끝난다고 할 때, 상근이가 이기려면 k-1번째에 경기가 끝났을 때 1, 3개 중에 남아야 하고, 0, 2개가 남으면 창영이가 이긴다.
|
||||
한 경기가 끝나면 2 or 4 or 6개의 돌이 없어지므로, 무조건 짝수개씩 사라지기 때문에 n이 짝수면 홀수개 즉, 1,3개가 절대 남을 수 없다.
|
||||
반대도 마찬가지이므로 n이 짝수면 창영이의 승리, n이 홀수면 상근이의 승리이다.
|
||||
|
||||
dp로 만들어보면 dp[i]는 i개의 돌이 있을 때 상근이의 승리 여부이다. (dp[i]=1 -> 상근이 승리)
|
||||
|
||||
dp[i-1]에서 상근이가 이겼다면 1개 가져와서 이긴 경우, dp[i]는 1개가 남으므로 창영이 승리
|
||||
dp[i-1]에서 상근이가 이겼다면 3개 가져와서 이긴 경우, dp[i]는 4개가 남으므로 어떻게 해도 창영이 승리
|
||||
dp[i-1]에서 상근이가 진 상황도 위와 그대로 반대이다. 따라서 dp[i] = 1-dp[i-1]
|
||||
|
||||
초기 dp는 0번째만 필요하므로 dp[0]=1 (돌이 1개이고, 상근이가 시작하니까)
|
||||
|
||||
dp[i]의 적절한 상황을 구성하고, i상황이 되기 위해 연관되는 i 이전의 상황들을 상정하여 dp 식을 세우면 된다.
|
||||
이번 상황은 i-1번째 상황만으로 i번째 상황이 결정된다.
|
||||
"""
|
||||
Reference in New Issue
Block a user