문제
미친로봇 (https://www.acmicpc.net/problem/1405)
풀이
1. 초기 접근
- 문제조건 해석
- 움직임, 경로에 대한 문제고, 횟수가 정해져 있다.
- DFS, BFS 문제.
- 확률을 구해야 하므로, DFS, BFS 마지막 스텝에서 지금까지 구한 확률을 모두 더해줘야겠다.
- 마지막 스텝에서 지금까지의 확률을 가지고있어야 하니, 인자로 지금까지의 확률을 넘겨줘야겠다.
- 움직임, 경로에 대한 문제고, 횟수가 정해져 있다.
- 알고리즘
- BFS가 먼저 떠올라 BFS로 구현.
- 코드
# 동서남북 순으로 방향 저장.
dxs = [0, 0, 1, -1]
dys = [1, -1, 0, 0]
def bfs(x, y):
q = [(x, y, 1)]
step = 1
answer = 0
visited = {(x, y)}
while q:
size = len(q)
next_visited = set()
for i in range(size):
x, y, ratio = q.pop(0)
for idx, (dx, dy) in enumerate(zip(dxs, dys)):
nx, ny = x + dx, y + dy
if (nx, ny) not in visited:
# 마지막 움직임인 경우, 모든 확률을 계산하여 더한다.
if step >= n:
answer += ratio * d_ratio[idx]
continue
# 아직 움직임이 남아있는 경우, 다음 방문지와 확률을 저장.
next_visited.add((nx, ny))
q.append((nx, ny, ratio * d_ratio[idx]))
visited |= next_visited
step += 1
return answer
line = list(map(int, input().split()))
n = line[0]
d_ratio = [i/100 for i in line[1:]]
print(bfs(0, 0))
2. 오류
틀렸다고 뜬다. 어디가 문제였을까.
한참 헤매던 중, BOJ Slack 에서, 랭커분이 이렇게 말씀하셨다.
로봇의 움직이는 어떤 경로 그 자체에 한 점이 두 번 나타나면 안 되는 것이지, 다른 경로에서 방문했던 점을 방문하면 안 되는 게 아닙니다.
그렇다… BFS 로 풀면 안된다. DFS 로 풀어야 한다.
한참 뻘짓거리 했다… 후아
3. 다시 제출
- 알고리즘
- DFS 로 바꾼 것 말고는 전반적인 아이디어는 이전과 동일하다.
- 처음에만 4방향으로 가고, 이후 3가지 방향으로 뻗어나가므로 (직전 방문한 노드방향으로는 가지않으므로), 시간 복잡도는 O(4 * 3^13) 이다. 이는 400만 정도로, 1억을 넘지않으므로 시간을 초과하지 않고 풀 수 있다.
- 코드
# 동서남북 순으로 방향 저장.
dxs = [0, 0, 1, -1]
dys = [1, -1, 0, 0]
def dfs(x, y, ratio, step):
if step >= n:
global answer
answer += ratio
return
visited.add((x,y))
for idx, (dx, dy) in enumerate(zip(dxs, dys)):
nx, ny = x + dx, y + dy
if (nx, ny) not in visited:
dfs(nx, ny, ratio * d_ratio[idx], step+1)
visited.remove((x,y))
line = list(map(int, input().split()))
n = line[0]
d_ratio = [i/100 for i in line[1:]]
visited, answer = set(), 0
dfs(0, 0, 1, 0)
print(answer)
'취업과 기본기 튼튼 > 코딩 테스트 노트' 카테고리의 다른 글
[BOJ] 1697. 숨바꼭질 (0) | 2019.04.07 |
---|---|
[BOJ] 9466. 텀 프로젝트 (0) | 2019.04.07 |
[삼성 SW Expert Academy] 1247. 최적 경로 (0) | 2019.04.02 |
[BOJ] 14888. 연산자 끼워넣기 (0) | 2019.04.02 |
파이썬으로 문제 풀 때 주의해야할 점들 (5) | 2019.03.26 |