내리막 길(DFS+DP)
2022. 12. 7. 15:16ㆍC++/알고리즘
https://www.acmicpc.net/problem/1520
1520번: 내리막 길
첫째 줄에는 지도의 세로의 크기 M과 가로의 크기 N이 빈칸을 사이에 두고 주어진다. 이어 다음 M개 줄에 걸쳐 한 줄에 N개씩 위에서부터 차례로 각 지점의 높이가 빈 칸을 사이에 두고 주어진다.
www.acmicpc.net
단순 DFS로만 알고리즘을 짜게되면 시간초과가 발생하게 된다
이전에 목표까지 도달했던 경로를 저장하여 추후 재도달시 바로 목표까지 도달한다고 판단하는
다이나믹 프로그래밍 기법을 사용해야 한다.
#include <iostream>
#include <stack>
using namespace std;
int x, y;
// input
int Matrix[500][500] = { 0, };
// 경로를 가짓수로 저장(DP)
int Check[500][500] = { 0, };
int xpos[4] = { 0, 1, 0, -1 };
int ypos[4] = { 1, 0, -1, 0 };
bool check(int nx, int ny)
{
if (nx >= 0 && nx < x && ny >= 0 && ny < y) return true;
else return false;
}
int DFS(int cx, int cy)
{
// 목표지점이면 1 반환
if (cx == x - 1 && cy == y - 1) return 1;
// 이미 이전에 도달했던 경로라면 저장된 값을 반환(DP)
if (Check[cx][cy] != -1) return Check[cx][cy];
// 방문판단을 위해 -1로 초기화 했으므로 현재 경로를 0으로 초기화
Check[cx][cy] = 0;
for (int i = 0; i < 4; i++)
{
int movex = cx + xpos[i];
int movey = cy + ypos[i];
if (check(movex, movey))
{
if (Matrix[cx][cy] > Matrix[movex][movey])
{
// 현재 값 + 다음 노드에 대한 DFS
Check[cx][cy] += DFS(movex, movey);
}
}
}
// 네 방향에 대해 경로탐색을 모두 끝냈다면
// 자기 자신을 반환(현재 위치부터 목표까지 도달하는 경우의 수)
return Check[cx][cy];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> x >> y;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
cin >> Matrix[i][j];
Check[i][j] = -1;
}
}
if (x == 1 && y == 1) Check[0][0] = 1;
else DFS(0, 0);
cout << Check[0][0] << '\n';
}
'C++ > 알고리즘' 카테고리의 다른 글
보석 도둑(Greedy) (0) | 2022.12.13 |
---|---|
빵집(DFS+Greedy) (0) | 2022.12.09 |
동전1(다이나믹 프로그래밍) (0) | 2022.11.01 |
N-Queen(백트래킹) (0) | 2022.10.06 |
N과 M(백트래킹) (0) | 2022.10.06 |