[Programmers][Python] 프로그래머스: 등굣길
1일 1PS 80일차!
📚 문제
[Level 3] - 등굣길
💡 풀이 과정
- 가장 기본적인 DP 문제이다.
- 점화식을 찾아내기도 쉽고 조건을 처리하기도 쉽다.
- 점화식은
- dp[x][y] = dp[x-1][y] + dp[x][y-1] 이다.
- 여기서 물웅덩이의 dp 값은 더해주지 않으면 되고 현재 위치가 물웅덩이라면 continue 하면 된다.
- 여기서 가장 주의할 점은 dp 값이 할당되지 않은 곳과 물웅덩이를 구별지어야한다.
- 만약 물웅덩이를 0 으로 둔다면 dp 를 더했을 때 0 이 더해져 따로 처리를 안해도 될 것 같지만
- 실제로는 해당 물웅덩이를 할당되지 않은 일반 dp 값과 구분할 수 없어 물웅덩이에 값이 채워진다.
- 따라서 여기에서는 물웅덩이를 -1 로 설정하였다.
- dp 의 초기값을 -1 로 설정하고 물웅덩이를 0 으로 해도 된다.
- 이제 순서대로 dp 를 처리하기만 하면 된다. dp 는 (1, 1) 에서 출발해 (4, 3) 까지 대각선으로 수행되어야한다.
- bfs 를 실행할 때의 처리 과정과 동일하다 볼 수 있다.
- 따라서 아래와 같이 bfs 를 진행해봤는데, 기존의 코드보다 훨씬 느리게 동작했다.
def bfs(N, M):
dx = [1, 0]
dy = [0, 1]
queue = deque()
queue.append((1,1))
visited = [[False for _ in range(M + 1)] for _ in range(N + 1)]
visited[1][1] = True
while queue:
x, y = queue.popleft()
for i in range(2):
nx = x + dx[i]
ny = y + dy[i]
if nx > N or ny > M or visited[nx][ny] or dp[nx][ny] == -1:
continue
sum = 0
if dp[nx - 1][ny] != -1:
sum += dp[nx - 1][ny]
if dp[nx][ny - 1] != -1:
sum += dp[nx][ny - 1]
dp[nx][ny] = sum % 1000000007
queue.append((nx, ny))
return dp[N][M]
return bfs(n, m)
- 결국 그냥 for 문을 사용하게 되었는데,
””” (1,1) (2,1) (1,2) … (4,3) “””
- 위와 같이 적용되어야한다.
- 보면 총 합이 2 ~ (n + m) 인 것을 확인할 수 있다.
- 또한 x <= n, y <= m 조건을 활용한다면 쉽게 해당 순서로 진행시킬 수 있다.
- 이제 물웅덩이 조건을 추가해야한다.
- 물웅덩이가 온 곳 (dp = -1) 은 경로를 더하지 않는다.
- 물웅덩이인 곳은 계산을 하지 않는다.
- 2번을 적용시키지 않으면 물웅덩이는 -1 에서 값이 업데이트되어 1번 상황이 일어나지 않는다.
- 두 조건을 잘 적용시키면 dp[n][m] 이 정답이다.
📌포인트
- dp
- dp 에서는 점화식을 세워 값을 더해나간다.
- dp 의 초기값을 모두 설정해주고 시작할 수도 있지만
- 0 값인 행과 열을 추가해 첫번째 행과 열 초기값 처리 없이 바로 진행할 수 있다.
- x, y
- 2차원 배열에서는 문제에서 주어진 값의 x, y 를 잘 확인해서 입력하자.
💻 코드
# 문제 조건!
# 1000000007 로 나눈 나머지를 return
def solution(m, n, puddles):
dp = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
# 처음 시작 지점
dp[1][1] = 1
# puddles 는 -1 로 설정
# 조건에서 x, y 위치 제대로 확인.
for px, py in puddles:
dp[py][px] = -1
# 위에서부터 대각선으로 탐색해야한다.
"""
(1,1)
(2,1) (1,2)
...
(4,3)
for i in range(m + n):
for j in range(1, i):
여기서 좌표는 (j, i-j)
이때 (1, 6), (2, 5) 등 i 는 n 보다 작아야하며, i - j 는 m 보다 작아야한다.
(i, j) 를 sum(i,j) 순서대로 오름차순 정렬해도 될 것 같긴 하다.
"""
# [1, 1] 은 이미 1로 지정해놓았으니 합이 3부터 해야한다.
for i in range(3, m + n + 1):
for j in range(1, i):
if j > n or i - j > m:
continue
if dp[j][i-j] == -1:
continue
# print(j, i-j)
# 여기서 dp 처리 ..
sum = 0
if dp[j - 1][i - j] != -1:
sum += dp[j - 1][i - j]
if dp[j][i - j - 1] != -1:
sum += dp[j][i - j - 1]
dp[j][i-j] = sum % 1000000007
return dp[n][m] % 1000000007
# 확인해야할 테스트케이스!
# dp 에서 외곽부분 처리..
댓글남기기