You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
## 1697번: 숨바꼭질#### 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.#### 수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.fromcollectionsimportdequen, k=map(int, input().split())
MAX=400000# 계산을 통해 도출해야함(2십만 권고) # O(V+E) = 1십만 + 3십만 = 4십만 넣어봄check= [False] * (MAX+1)
d= [-1]*(MAX+1)
q=deque()
q.append(n)
d[n] =0# 문제조건에서 출발점에선 0초이므로 0으로 초기화check[n] =Truewhileq:
now=q.popleft()
fornextin [now-1, now+1, 2*now]:
if0<=next<=MAXandcheck[next] ==False: # next가 아직 방문한 적 없는 위치이고 && 범위 안에 있다면,check[next] =True# (1)방문처리q.append(next) # (2) 방문할 큐에 추가d[next] =d[now] +1# (3) 최단거리 업데이트print(d[k])
5 17
4
13913번: 숨바꼭질 4
이동해야 하는 경로 추가 출력
## 13913번: 숨바꼭질 4#### 이동해야 하는 경로 추가 출력 (재귀함수로 경로 역추적)fromcollectionsimportdequeimportsysn, k=map(int, input().split())
MAX=400000# 계산을 통해 도출해야함(2십만 권고) # O(V+E) = 1십만 + 3십만 = 4십만 넣어봄sys.setrecursionlimit(MAX)
check= [False] * (MAX+1)
d= [-1]*(MAX+1)
q=deque()
via= [-1] * (MAX+1) ## 경로를 담는 배열 추가 !q.append(n)
d[n] =0# 문제조건에서 출발점에선 0초이므로 0으로 초기화check[n] =Truewhileq:
now=q.popleft()
fornextin [now-1, now+1, 2*now]:
if0<=next<=MAXandcheck[next] ==False: # next가 아직 방문한 적 없는 위치이고 && 범위 안에 있다면,check[next] =True# (1)방문처리q.append(next) # (2) 방문할 큐에 추가d[next] =d[now] +1# (3) 최단거리 업데이트via[next] =now## (4) 경로 역추적 배열 추가 !print(d[k]) # 1. 거리 출력defgo(n, k): # 2. 경로 출력 (재귀함수 이용)ifn!=k:
go(n, via[k])
print(k, end=' ')
go(n,k)
5 17
4
5 4 8 16 17
14226번: 이모티콘
3가지 연산(1.클립보드에 저장, 2.화면에 붙여넣기, 3.화면에 있는 이모티콘 1개 삭제)만 사용해, S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오.
모든 연산은 1초 (이미 화면에 이모티콘 1개를 입력한 상태)
## 14226번: 이모티콘#### 3가지 연산(1.클립보드에 저장, 2.화면에 붙여넣기, 3.화면에 있는 이모티콘 1개 삭제)만 사용해, S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오.#### 모든 연산은 1초 (이미 화면에 이모티콘 1개를 입력한 상태)# 파란간선 BFS 문제 (2차원 dist배열 이용)# (현재 화면에 있는 이모티콘 개수, 현재 클립보드에 있는 이모티콘 개수) = (s, c)fromcollectionsimportdequen=int(input())
dist= [[-1]*(n+1) for_inrange(n+1)]
q=deque()
q.append((1, 0)) # 출발점dist[1][0] =0# (s,c) = (1,0)에서 출발, 시작은 0초whileq:
s, c=q.popleft() # 2차원ifdist[s][s] ==-1: # 연산 1: (s, c) -> (s, s)dist[s][s] =dist[s][c] +1q.append((s,s))
ifs+c<=nanddist[s+c][c] ==-1: # 연산 2: (s, c) -> (s+c, c)dist[s+c][c] =dist[s][c] +1q.append((s+c,c))
ifs-1>=0anddist[s-1][c] ==-1: # 연산 3: (s, c) -> (s-1, c)dist[s-1][c] =dist[s][c] +1q.append((s-1,c))
#print(dist)# 답 출력ans=-1foriinrange(n+1):
ifdist[n][i] !=-1:
ifans==-1orans>dist[n][i]:
ans=dist[n][i] # 최소값으로 교체print(ans)
2
[[1, 2, 5], [0, 1, 4], [-1, 2, 3]]
2
13549번: 숨바꼭질 3
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
## 13549번: 숨바꼭질 3#### 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.#### 수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.fromcollectionsimportdequeMAX=2000000check= [False]*MAXdist= [-1]*MAXn, m=map(int, input().split())
check[n] =True# 출발점: 수빈이의 위치 ndist[n] =0# 출발시각: 0초에서 시작q=deque() # (1)현재 큐 선언next_queue=deque() # (2)다음 큐 선언q.append(n)
whileq:
now=q.popleft()
# (1) 시간이 0초 걸리는 연산 -> "현재 큐"에 추가ifnow*2<MAXandcheck[now*2] ==False: # 연산을 통해 이동할 위치가 범위 안에 있고 & 아직 방문하지 않았다면,q.append(now*2)
check[now*2] =Truedist[now*2] =dist[now] # 현재시간 그대로# (2) 시간이 1초 걸리는 연산 -> "다음 큐"에 추가ifnow+1<MAXandcheck[now+1] ==False: # 연산을 통해 이동할 위치가 범위 안에 있고 & 아직 방문하지 않았다면,next_queue.append(now+1)
check[now+1] =Truedist[now+1] =dist[now] +1# 현재시간에 1초 더해서 업데이트ifnow-1>=0andcheck[now-1] ==False: # 연산을 통해 이동할 위치가 범위 안에 있고 & 아직 방문하지 않았다면,next_queue.append(now-1)
check[now-1] =Truedist[now-1] =dist[now] +1# 현재시간에 1초 더해서 업데이트## 현재 큐가 남아있지 않다면 -> 다음 큐로 넘어가기ifnotq:
q=next_queue# 다음 큐가 "현재 큐"가 되고,next_queue=deque() # 새로운 "다음 큐" 생성print(dist[m])
5 17
2
덱(양방향 링크드리스트)를 활용한 풀이법
# 덱 사용# 연산 0초는 덱의 앞쪽으로 삽입, 연산 1초는 덱의 뒷쪽으로 삽입fromcollectionsimportdequeMAX=2000000check= [False]*MAXdist= [-1]*MAXn, m=map(int, input().split())
check[n] =Truedist[n] =0q=deque()
q.append(n)
whileq:
now=q.popleft()
# (1) 시간이 0초 걸리는 연산 -> "현재 큐"에 추가ifnow*2<MAXandcheck[now*2] ==False: # 연산을 통해 이동할 위치가 범위 안에 있고 & 아직 방문하지 않았다면,q.appendleft(now*2) ## 덱의 앞에 삽입check[now*2] =Truedist[now*2] =dist[now] # 현재시간 그대로# (2) 시간이 1초 걸리는 연산 -> "다음 큐"에 추가ifnow+1<MAXandcheck[now+1] ==False: # 연산을 통해 이동할 위치가 범위 안에 있고 & 아직 방문하지 않았다면,q.append(now+1) ## 덱의 뒤에 삽입check[now+1] =Truedist[now+1] =dist[now] +1# 현재시간에 1초 더해서 업데이트ifnow-1>=0andcheck[now-1] ==False: # 연산을 통해 이동할 위치가 범위 안에 있고 & 아직 방문하지 않았다면,q.append(now-1) ## 덱의 뒤에 삽입check[now-1] =Truedist[now-1] =dist[now] +1# 현재시간에 1초 더해서 업데이트print(dist[m])
5 17
2
1261번: 알고스팟
이동할 수 있는 방은 (x+1, y), (x, y+1), (x-1, y), (x, y-1) 이다. 단, 미로의 밖으로 이동 할 수는 없다.
현재 (1, 1)에 있는 알고스팟 운영진이 (N, M)으로 이동하려면 벽을 최소 몇 개 부수어야 하는지 구하는 프로그램을 작성하시오.
## 1261번: 알고스팟#### 이동할 수 있는 방은 (x+1, y), (x, y+1), (x-1, y), (x, y-1) 이다. 단, 미로의 밖으로 이동 할 수는 없다.#### 현재 (1, 1)에 있는 알고스팟 운영진이 (N, M)으로 이동하려면 벽을 최소 몇 개 부수어야 하는지 구하는 프로그램을 작성하시오.## BFS 탐색을 벽을 부순 횟수에 따라서 나누어서 수행해야 한다 !# 빈방: 0, 벽: 1# 가중치 1) 빈방 -> 빈방 : 가중치 "0"# 가중치 2) 빈방 -> 벽 : 가중치 "1"fromcollectionsimportdequem, n=map(int, input().split()) # 가로, 세로a= [list(map(int, list(input()))) for_inrange(n)]
#print(a)dx= [0, 1, 0, -1]
dy= [-1, 0, 1, 0]
###check = [[False]*m for _ in range(n)]dist= [[-1]*mfor_inrange(n)]
###check[0] = True # 출발점dist[0][0] =0# 벽 부수는 초기횟수: 0번q=deque() # (1)현재 큐 선언next_queue=deque() # (2)다음 큐 선언q.append((0,0))
whileq:
x, y=q.popleft()
forkinrange(4):
nx, ny=x+dx[k], y+dy[k]
if0<=nx<nand0<=ny<m: ## 세로, 가로ifdist[nx][ny] ==-1: # next 좌표가 범위 내 있고 && 아직 방문한 적 없다면,ifa[nx][ny] ==0: # (1)빈방으로 갈 때 (가중치 0)q.append((nx, ny))
###check[nx][ny] = Truedist[nx][ny] =dist[x][y] # 현재 횟수 그대로else: # (2)벽으로 갈 때 (가중치 1)next_queue.append((nx, ny))
###check[nx][ny] = Truedist[nx][ny] =dist[x][y] +1# 현재 횟수에 1 추가## 현재 큐가 남아있지 않다면 -> 다음 큐로 넘어가기ifnotq:
q=next_queue# 다음 큐가 "현재 큐"가 되고,next_queue=deque() # 새로운 "다음 큐" 생성print(dist[n-1][m-1])
3 3
011
111
110
3
덱(양방향 링크드리스트)를 활용한 풀이법
# 덱으로 구현fromcollectionsimportdequem, n=map(int, input().split()) # 가로, 세로a= [list(map(int, list(input()))) for_inrange(n)]
#print(a)dx= [0, 1, 0, -1]
dy= [-1, 0, 1, 0]
###check = [[False]*m for _ in range(n)]dist= [[-1]*mfor_inrange(n)]
###check[0] = True # 출발점dist[0][0] =0# 벽 부수는 초기횟수: 0번q=deque() # 덱 선언q.append((0,0))
whileq:
x, y=q.popleft()
forkinrange(4):
nx, ny=x+dx[k], y+dy[k]
if0<=nx<nand0<=ny<m: ## 세로, 가로ifdist[nx][ny] ==-1: # next 좌표가 범위 내 있고 && 아직 방문한 적 없다면,ifa[nx][ny] ==0: # (1)빈방으로 갈 때 (가중치 0)q.appendleft((nx, ny)) ## 덱 앞에 삽입###check[nx][ny] = Truedist[nx][ny] =dist[x][y] # 현재 횟수 그대로else: # (2)벽으로 갈 때 (가중치 1)q.append((nx, ny)) ## 덱 뒤에 삽입###check[nx][ny] = Truedist[nx][ny] =dist[x][y] +1# 현재 횟수에 1회 추가print(dist[n-1][m-1])