[DFS + DP] 백준 1520번: 내리막길(Swift)

2022. 11. 11. 13:24·코테

https://www.acmicpc.net/problem/1520

 

1520번: 내리막 길

여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으

www.acmicpc.net

 

 

난이도: 골드 3
사용언어: Swift
카테코리: DFS + DP
풀이과정

문제를 보자마자 단순 DFS 문제라고 생각해서 DFS만 이용하여 탐색하였다.

하지만, 첫 제출에서 시간 초과가 발생...

시간 초과의 원인은, 문제 특성상 map에서 다른 경로이지만, 중복되는 경로가 존재할 수 있다. 가령

위 그림 처럼 50부터 32까지 두 경로가 겹친다. 이런점을 이용하여 DP(Dynamic Programming)를 이용하여 시간 초과를 해결할 수 있었다.

 

DP는 해당 지점의 경우의 수를 저장해 두어야한다. 먼저,

탐색이 종착지에 도착하면, dfs 메서드는 1을 리턴하도록 하여 한가지 경우의 수를 찾았다는 의미이다.

반복문, 내부에서는 다음 이동할 좌표에 DP가 0보다 크면, 이미 탐색을 했고, 해당 지점부터 종착지 까지 경우의 수를 구한 상태 이를 해당(start) 좌표에 + 해준다.

이동할 좌표에 DP가 0이면, 아직 탐색이 되지 않은 상태이기 때문에 dfs를 재귀로 호출하여 종착지 또는 DP가 0보다 큰 지점이 나올때 까지 탐색한다.

 

반복문이 끝나고, 해당 좌표의 DP가 0이면 종착지까지 가지 못했다는 의미이기 때문에 해당 경로를 탐색하지 않기 위해 -1을 리턴하여 해당 경로는 탐색하지 않게 하고, 0이 아니면, 해당 좌표의 DP를 반환하여 부모 좌표의 DP에 + 될 수 있도록 한다.

 

code
let mn = readLine()!.split(separator: " ").map { Int($0)! }
let m = mn[0]
let n = mn[1]

var map = [[Int]]()
var dp = Array(repeating: Array(repeating: 0, count: n), count: m)

for _ in 0..<m {
  let y = readLine()!.split(separator: " ").map { Int($0)! }
  map.append(y)
}

let direction: [(y: Int, x: Int)] = [
  (0,-1),
  (0,1),
  (-1,0),
  (1,0)
]



func dfs(start: (y: Int, x: Int)) -> Int {
  if start == (m - 1, n - 1) {
    return 1
  }
  
  for i in 0..<direction.count {
    let nP: (y: Int, x: Int) = (start.y + direction[i].y, start.x + direction[i].x)
    if (0..<m).contains(nP.y) &&
        (0..<n).contains(nP.x) &&
        map[start.y][start.x] > map[nP.y][nP.x] {
      if dp[nP.y][nP.x] > 0 {
        dp[start.y][start.x] += dp[nP.y][nP.x]
      } else if dp[nP.y][nP.x] == 0 {
        dp[start.y][start.x] += dfs(start: nP)
      }
    }
  }
  if dp[start.y][start.x] == 0 {
    dp[start.y][start.x] = -1
    return 0
  } else {
    return dp[start.y][start.x]
  }
}

let result = dfs(start: (0, 0))
print(result == -1 ? 0 : result)

 

'코테' 카테고리의 다른 글

[BFS + 구현] 백준 2573번: 빙산  (0) 2022.11.14
[DFS] 백준 1707번: 이분 그래프(Swift)  (0) 2022.11.11
[DFS] 백준 2644번: 촌수계산(Swift)  (0) 2022.11.09
[BFS] 백준: 영역 구하기(Swift)  (0) 2022.11.08
[DFS] 백준 11725번: 트리의 부모 찾기(Swift)  (0) 2022.11.07
'코테' 카테고리의 다른 글
  • [BFS + 구현] 백준 2573번: 빙산
  • [DFS] 백준 1707번: 이분 그래프(Swift)
  • [DFS] 백준 2644번: 촌수계산(Swift)
  • [BFS] 백준: 영역 구하기(Swift)
Esiwon
Esiwon
iOS 개발 블로그
  • Esiwon
    시원한 코드 기록
    Esiwon
  • 전체
    오늘
    어제
    • 분류 전체보기 (70)
      • iOS&Swift (24)
      • git & github (1)
      • 코테 (41)
      • 네부캠 회고 (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    재귀
    GCD
    Property wrapper
    비동기
    그리디
    ios
    구현
    챌린지
    알고리즘
    Combine
    PhotoKit
    코테
    Race Condition
    photos
    실버
    코딩테스트
    네부캠
    백준
    동시성
    이분탐색
    dfs
    회고
    브루트포스 알고리즘
    BFS
    photoUI
    노드
    다이나믹 프로그래밍
    탐색
    완전탐색
    Swift
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Esiwon
[DFS + DP] 백준 1520번: 내리막길(Swift)
상단으로

티스토리툴바