====== DSLR ======
===== 풀이 =====
* BFS로 최단 경로를 찾고, 기본적인 경로추적을 적용해서 경로를 출력하는 문제.
* 각 숫자가 노드가 되므로 노드는 총 10000개, 한 숫자에서 변환 방법이 4가지이므로 엣지는 4*10000 개. BFS로 풀면 O(40000)수준이므로 별 문제가 되지는 않아야 한다.
* 하지만, python으로 통과하기가 꽤나 힘든데, 테스트 케이스가 상당히 많이 들어있는 것 같다. 평범하게 짠 코드로는 python3으로는 시간 초과, pypy로도 5360ms나 걸려서 통과되었다.
* 시간을 단축시키기 위해서 여러가지로 애를 쓴 결과, python으로 13704ms에 통과시키는 데에 성공했다..
* 튜플 생성을 최대한 줄인다 -> 도달한 각 숫자에 대해서 기존 숫자와 명령을 튜플로 저장하는 대신에, 기존 숫자만 리스트에 저장하고, 나중에 출력할때에 명령을 다시 계산해서 찾는다. 불필요한 작업이 추가되는 것 같지만 이 편이 속도가 빠르다.
* 각 숫자에서 변환될수 있는 다음 숫자들의 테이블을 모든 숫자에 대해서 처음에 계산해두고 계속 재활용해서 사용한다
* 4가지 변환을 처리하는 부분을 for문으로 처리하는 대신, 그냥 비슷한 구문을 4번 반복해서 작성했다. 속도 차이가 꽤나 난다
* 가장 빠른 코드는 이 문제를 3004ms에 통과했다. 메모리 사용량도 평범하다. 이것은 내 로직을 쥐어짜서 최적화 한다고 해서 도달할수 있는 레벨이 아니고 뭔가 새로운 아이디어가 들어갔을 것 같은데, 코드 공개가 되어있지 않아서 확인이 불가능하다. 매우 궁금하다..
===== 코드 =====
==== 코드 1 - pypy3으로만 통과 ====
"""Solution code for "BOJ 9019. DSLR".
- Problem link: https://www.acmicpc.net/problem/9019
- Solution link: http://www.teferi.net/ps/problems/boj/9019
Tags: [BFS]
"""
import collections
import sys
def bfs(source, sink):
deq = collections.deque([source])
prev_state_and_cmd = [None] * 10000
while True:
n = deq.popleft()
next_states = [('D', n * 2 % 10000),
('S', n - 1 if n > 0 else 9999),
('L', n % 1000 * 10 + n // 1000),
('R', n % 10 * 1000 + n // 10)]
for cmd, v in next_states:
if prev_state_and_cmd[v] is None:
prev_state_and_cmd[v] = (n, cmd)
if v == sink:
return prev_state_and_cmd
deq.append(v)
def main():
T = int(sys.stdin.readline())
for _ in range(T):
A, B = [int(x) for x in sys.stdin.readline().split()]
prev_state_and_cmd = bfs(A, B)
cur = B
cmds = []
while cur != A:
cur, cmd = prev_state_and_cmd[cur]
cmds.append(cmd)
print(''.join(reversed(cmds)))
if __name__ == '__main__':
main()
==== 코드 2 - 안 예쁘지만 python3으로 통과 가능 ====
"""Solution code for "BOJ 9019. DSLR".
- Problem link: https://www.acmicpc.net/problem/9019
- Solution link: http://www.teferi.net/ps/problems/boj/9019
Tags: [BFS]
"""
import collections
import sys
def bfs(source, sink, next_states):
deq = collections.deque([source])
prev = [None] * 10000
while True:
n = deq.popleft()
d, s, l, r = next_states[n]
if prev[d] is None:
prev[d] = n
deq.append(d)
if prev[s] is None:
prev[s] = n
deq.append(s)
if prev[l] is None:
prev[l] = n
deq.append(l)
if prev[r] is None:
prev[r] = n
deq.append(r)
if prev[sink] is not None:
return prev
def main():
next_states = [[n * 2 % 10000,
(n - 1) % 10000,
n % 1000 * 10 + n // 1000,
n % 10 * 1000 + n // 10] for n in range(10000)]
T = int(sys.stdin.readline())
for _ in range(T):
A, B = [int(x) for x in sys.stdin.readline().split()]
prev_states = bfs(A, B, next_states)
cur = B
cmds = []
while cur != A:
prev = prev_states[cur]
cmd = next_states[prev].index(cur)
cmds.append('DSLR'[cmd])
cur = prev
print(''.join(reversed(cmds)))
if __name__ == '__main__':
main()
{{tag>BOJ ps:problems:boj:골드_5}}