[Gold III]
https://www.acmicpc.net/problem/1520
1520번: 내리막 길
여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으
www.acmicpc.net
풀이 1
Bottom-Up 방식의 DP.
오른쪽 아래부터 왼쪽 위까지 채워나가는 방식으로 구현했다.
오른쪽과 아래로만 갈 수 있는 줄 알았는데, 위와 왼쪽으로도 갈 수 있어서 WA.
#include <algorithm>
#include <iostream>
#include <vector>
#define init cin.tie(0)->ios_base::sync_with_stdio(0);
typedef long long ll;
using namespace std;
int main() {
init;
int M, N;
cin >> M >> N;
int v[M + 1][N + 1];
int h;
for (int i = 1; i < M + 1; i++) {
for (int j = 1; j < N + 1; j++) {
cin >> h;
v[i][j] = h;
}
}
ll dp[M + 1][N + 1];
fill(&dp[0][0], &dp[M][N], 0);
dp[M][N] = 1;
// 마지막 열
for (int i = M - 1; i > 0; i--) {
if (v[i + 1][N] < v[i][N]) dp[i][N] = 1;
}
// 마지막 행
for (int j = N - 1; j > 0; j--) {
if (v[M][j + 1] < v[M][j]) dp[M][j] = 1;
}
// dp
for (int i = M - 1; i > 0; i--) {
for (int j = N - 1; j > 0; j--) {
// 오른쪽으로 갈 수 있는가
if (v[i][j + 1] < v[i][j]) dp[i][j] += dp[i][j + 1];
// 아래로 갈 수 있는가
if (v[i + 1][j] < v[i][j]) dp[i][j] += dp[i + 1][j];
}
}
cout << dp[1][1];
}
풀이 2
상하좌우 4방향으로 갈 수 있었기에, DFS를 이용해 Top-Down 방식으로 풀이했다.
상하좌우 중 갈 수 있는 지 확인한 후 재귀 호출. (line 20~23)
난이도에 비해 크게 어렵지 않았던 문제.
AC.
#include <algorithm>
#include <iostream>
#include <vector>
#define init cin.tie(0)->ios_base::sync_with_stdio(0);
typedef long long ll;
using namespace std;
int v[502][502];
ll dp[502][502];
int M, N;
int dfs(int i, int j) {
if (i < 1 || i > M || j < 1 || j > N) return 0;
if (i == M && j == N) return 1;
// Memoization
if (dp[i][j] != -1) return dp[i][j];
ll ret = 0;
if (v[i][j] > v[i + 1][j]) ret += dfs(i + 1, j);
if (v[i][j] > v[i][j + 1]) ret += dfs(i, j + 1);
if (v[i][j] > v[i - 1][j]) ret += dfs(i - 1, j);
if (v[i][j] > v[i][j - 1]) ret += dfs(i, j - 1);
return dp[i][j] = ret;
}
int main() {
init;
cin >> M >> N;
int h;
for (int i = 1; i < M + 1; i++) {
for (int j = 1; j < N + 1; j++) {
cin >> h;
v[i][j] = h;
}
}
for (int i = 0; i < M + 2; i++) {
v[i][N + 1] = 10001;
v[i][0] = 10001;
}
for (int j = 0; j < N + 2; j++) {
v[M + 1][j] = 10001;
v[0][j] = 10001;
}
fill(&dp[0][0], &dp[M][N], -1);
cout << dfs(1, 1);
}