728x90
Original Source: https://www.acmicpc.net/problem/14226
14226번: 이모티콘
영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다. 영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만
www.acmicpc.net
문제
영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다.
영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만들어 보려고 한다.
- 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장한다.
- 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기 한다.
- 화면에 있는 이모티콘 중 하나를 삭제한다.
모든 연산은 1초가 걸린다. 또, 클립보드에 이모티콘을 복사하면 이전에 클립보드에 있던 내용은 덮어쓰기가 된다. 클립보드가 비어있는 상태에는 붙여넣기를 할 수 없으며, 일부만 클립보드에 복사할 수는 없다. 또한, 클립보드에 있는 이모티콘 중 일부를 삭제할 수 없다. 화면에 이모티콘을 붙여넣기 하면, 클립보드에 있는 이모티콘의 개수가 화면에 추가된다.
영선이가 S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 S (2 ≤ S ≤ 1000) 가 주어진다.
출력
첫째 줄에 이모티콘을 S개 만들기 위해 필요한 시간의 최솟값을 출력한다.
사고의 흐름
더보기
- 그리디로 이 문제를 풀 수는 없다. S의 값에 따라서 제일 효율적인 연산의 종류와 순서가 천차만별로 달라지기 때문이다.
- 걸리는 시간의 최솟값을 구하라고 했으니 BFS을 이용해 탐색하는 것이 타당하다.
- 굳이 이모티콘을 문자열로 처리할 필요는 없다. 어차피 이모티콘의 종류가 1가지밖에 없으니 이모티콘의 갯수만 알면 된다.
- 클립보드를 잘 구현하는 것이 관건일 것 같다.
- 처음에는 복사, 붙여넣기를 계속 번갈아 한다고 생각했는데, 다시 생각해 보니 복사를 한 번 해 두면 재복사를 할 필요 없이 붙여넣기를 연속으로 할 수 있었다.
- 단, 화면 내 이모티콘의 숫자와 클립보드에 저장된 이모티콘의 숫자가 같을 때는 다시 복사를 할 필요가 없다.
- 단순히 dist List의 원소와 cnt만을 비교하면 안 된다. 비교하는 두 노드의 클립보드 이모티콘의 숫자가 서로 다르면 향후 둘의 붙여넣기 연산의 결과가 다르므로, 두 노드를 모두 고려해야 하기 때문이다.
내가 작성한 소스코드
import sys
from collections import deque
def bfs(end, visited):
q = deque()
emo_num = 1; cnt = 0; clipboard = 0
visited[emo_num][clipboard] = 0
q.append((emo_num, cnt, clipboard))
while q:
emo_num = q[0][0]
cnt = q[0][1]
clipboard = q[0][2]
q.popleft()
if emo_num == end:
print(cnt)
return
if emo_num != clipboard:
if visited[emo_num][emo_num] == False:
visited[emo_num][emo_num] = True
q.append((emo_num, cnt+1, emo_num))
if clipboard > 0 and emo_num+clipboard <= 2000:
if visited[emo_num+clipboard][clipboard] == False:
visited[emo_num+clipboard][clipboard] = True
q.append((emo_num+clipboard, cnt+1, clipboard))
if emo_num-1 >= 2:
if visited[emo_num-1][clipboard] == False:
visited[emo_num-1][clipboard] = True
q.append((emo_num-1, cnt+1, clipboard))
visited = [[False] * 2001 for _ in range(2001)]
s = int(sys.stdin.readline().rstrip())
bfs(s, visited)
남이 작성한 소스코드
얍문 님:
https://yabmoons.tistory.com/74
degurii 님:
https://degurii.tistory.com/162
피드백
- BFS에서 방문 처리 List를 만들 때는 각각의 경로를 나누는 기준에 따라 List의 차원의 개수를 결정해야 한다. 이번 문제에서는 화면의 이모티콘 수, 클립보드의 이모티콘 수의 2개의 기준이 있었으므로 방문 처리 List를 2차원으로 만들어야 했다.
- 모든 Backtracking 문제가 그런 것은 아니지만, 이 문제는 DFS와 BFS를 둘 다 사용할 수 있는 문제이다. BFS로 풀었던 문제들을 나중에 다시 DFS로 풀어보면 좋겠다.
'BOJ' 카테고리의 다른 글
[골드 4] 1261번: 알고스팟 (0) | 2022.09.16 |
---|---|
[실버 2] 3085번: 사탕 게임 (0) | 2022.09.15 |
[골드 4] 13913번: 숨바꼭질 4 (0) | 2022.09.14 |
[실버 1] 1697번: 숨바꼭질 (0) | 2022.09.12 |
[실버 4] 2407번: 조합 (0) | 2022.09.11 |