Krafton_Jungle/Study
Krafton_jungle 5기 24일차 TIL - 알고리즘
전낙타
2024. 4. 10. 23:18
11723 집합
import sys
input = sys.stdin.readline
def add(S, x):
x = int(x)
S |= (1 << x) # 1을 X만클 shift 연산 한 뒤 or연산 실행
return S
def remove(S, x):
x = int(x)
S &= ~(1 << x) # 1을 X만클 shift 연산 한 뒤 NAND연산 실행
return S
def check(S, x):
x = int(x)
if S & (1 << x): #
return True
return False
def toggle(S, x):
x = int(x)
S ^= 1 << x
return S
def all():
S = (1 << 21) - 1
return S
def empty():
return 0
n = int(input())
S = 0
for i in range(n):
commend = list(input().split())
if commend[0] == "add":
S = add(S, commend[1])
elif commend[0] == "remove":
S = remove(S, commend[1])
elif commend[0] == "check":
if check(S, commend[1]):
print(1)
continue
print(0)
elif commend[0] == "toggle":
S = toggle(S, commend[1])
elif commend[0] == "all":
S = all()
elif commend[0] == "empty":
S = empty()
외판원 순회에서 비트 마스킹 기법을 사용해야 한다고 해서 익숙해질 겸 풀어본 문제.
확실히 이렇게 집합을 활용하면 정말 편하게 방문 처리를 할 수 있다는 사실을 알게되었다.
2098 외판원 순회
import sys
import math
input = sys.stdin.readline
n = int(input())
inf = math.inf
container = []
for i in range(n):
row = list(map(int, input().split()))
container.append(row)
dp = [[-1] * (1 << n) for _ in range(n)]
def dfs(start, visited):
# 탈출조건
if visited == (1 << n)-1:
if container[start][0]:
return container[start][0]
else:
return inf
if dp[start][visited] != -1:
return dp[start][visited]
min_val = inf
# DP 조건
for next in range(1, n):
# 이미 방문 했거나 연결되어있지 않으면
if container[start][next] == 0 or visited & (1 << next):
continue
cost = dfs(next, visited | (1 << next)) + container[start][next]
min_val = min(min_val, cost)
dp[start][visited] = min_val
return min_val
print(dfs(0, 1))
기존에 풀었던 외판원 순회 2와 DP, 비트마스킹을 추가해서 풀이했다.
1931 회의실 배정
#실패코드!
import sys
import heapq
input = sys.stdin.readline
n = int(input())
max_distance = 0
room = []
for i in range(n):
start, end = map(int, input().split())
distance = end - start
max_distance = max(max_distance, end)
heapq.heappush(room, (distance, start, end))
visited = [0] * (max_distance + 1)
res = 0
while room:
distance, start, end = heapq.heappop(room)
if start == end:
if visited[start] == 1:
continue
else:
visited[start] = 1
res += 1
continue
for i in range(start, end):
if visited[i] == 1:
break
else:
for i in range(start, end):
visited[i] = 1
res += 1
print(res)
내 생각엔 거리를 기준으로 우선순위 큐에 담아 나열하는 방식으로 접근했다.
하지만 이 코드의 치명적인 오류가 있는데 시작점과 끝점이 같은 경우엔 무조건 count가 오른다는 부분.
애초에 접근 방식이 잘못됐다고 생각하고 코드를 한번 다 밀었다.
#성공코드
import sys
input = sys.stdin.readline
n = int(input())
room = [list(map(int, input().split())) for _ in range(n)]
room.sort(key=lambda x : (x[1], x[0]))
current = 0
cnt = 0
for i, j in room:
if i < current:
continue
current = j
cnt += 1
print(cnt)
생각해보니 끝점을 기준으로 정렬하고, 해당 시작점이 방금 전 끝점보다 작지 않으면 카운트를 해주는 방식으로 해결한다는 결론에 도달했다.
1946 신입사원
import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
n = int(input())
member = list()
res = 0
for _ in range(n):
member.append(list(map(int, input().split())))
member.sort(key=lambda x: x[0])
x = member[0][1]
for i in member:
if i[1] > x:
continue
else:
x = i[1]
res += 1
print(res)
이 문제도 사실상 회의실 배정 2인 셈이다.
DP는 풀이하는데 점화식을 찾는 재미라도 있었다면, 그리디는 정말 풀면풀수록 스트레스만 받는 유형인것 같다.