-
백준 1520번 : 내리막 길알고리즘 공부 2020. 4. 2. 16:43
처음에는 최단거리이면서 내리막길을 구하는 것인줄 알고 쉽네?! 하면서 했서 틀렸다... ㅋㅋ 문제를 잘 읽도록 하자.
단순 DFS만 적용하면 타임아웃이 날게 뻔하기 때문에 DP를 이용해 기록해두면 된다.
일단 DFS로 설명하면 (0, 0)에서 (x, y)로 가는 경로의 수를 count(x, y)라고 하자. (x, y)로 올 수 있는 경로는 다음 4가지이다.
(x, y)로 갈 수 있는 장소 하지만 이 4 장소가 모두 유효한 장소는 아니다. 이들에 대해 2가지 조건이 붙는다.
- 지도에 존재하는 장소일 것
- (x, y)보다 값이 클 것 (같아서도 안된다!)
만약 위 두 조건을 모두 만족하는 위치가 (x - 1, y)와 (x, y + 1)이였다면 count(x ,y)는 다음과 같다.
순수 DFS로는 이렇게 되지만 매번 count함수를 통해 값을 구할 경우 구했던 장소를 또 구하고 또 구하는 불필요한 동작이 반복된다. 따라서 어딘가에 기록해두고 값이 있다면 가져와서 쓰고 없다면 count함수를 실행시키면 된다.
나는 cnt라는 2차원 배열에 기록을 해두었고 최초에 cnt 배열을 -1로 초기화해서 -1이면 값이 없다고 생각하고 그 좌표에 대한 count 함수를 실행했다.
#include <stdio.h> #include <iostream> using namespace std; int n, m; int dx[4] = { 1, -1, 0, 0 }; int dy[4] = { 0, 0, 1, -1 }; int arr[500][500]; int cnt[500][500]; int count(int x, int y) { if(cnt[x][y] != -1) return cnt[x][y]; cnt[x][y] = 0; for(int i = 0; i < 4; i++) { int nx = x + dx[i]; int ny = y + dy[i]; if(0 <= nx && nx < n && 0 <= ny && ny < m) { if(arr[x][y] < arr[nx][ny]) { cnt[x][y] += count(nx, ny); } } } return cnt[x][y]; } int main() { cin >> n >> m; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { cin >> arr[i][j]; cnt[i][j] = -1; } } cnt[0][0] = 1; cout << count(n - 1, m - 1); return 0; }
'알고리즘 공부' 카테고리의 다른 글
백준 14002번 : 가장 긴 증가하는 부분 수열 4 (0) 2020.04.04 백준 2225번 : 합분해 (0) 2020.04.03 백준 2167번 : 2차원 배열의 합 (0) 2020.04.01 백준 11055번 : 가장 큰 증가 부분 수열 (0) 2020.03.31 백준 1699번 : 제곱수의 합 (0) 2020.03.30