백준 1520 - 내리막 길

1 minute read

문제링크

문제설명

image

문제접근

  • DFS + DP 로 해결한다.
    • DFS 로 완전탐색을 할 수도 있지만 모든 칸에서 4개의 방향으로 탐색할 때 최악의 경우 4 x 500 x 500 만큼의 시간이 필요하므로 시간 초과에 걸린다.
    • 이미 알고 있는 경로는 탐색하지 않는 메모이제이션 기법을 활용한다.
  • dist[r][c] 는 (r,c) 위치에서 목적지 (M, N) 까지 도달하는 경우의 수가 담긴다. dist[r][c] == -1 인 경우 (r,c) 에서 목적지 (N, M) 까지 경로를 탐색한 적이 없다는 것을 의미한다.

구현

#include <iostream>
#include <vector>
#include <memory.h>

#define MAX 501
using namespace std;

int M, N;
int board[MAX][MAX];
int dist[MAX][MAX];
int dx[4] = { -1, 1, 0, 0 };
int dy[4] = { 0, 0, -1, 1 };

int dfs(int cxpos, int cypos)
{
    // 목적지에 도달한 경우
	if (cxpos == M && cypos == N) return 1;
    // 이미 목적지까지 도달하는 경우의 수가 정해진 경우
	if (dist[cxpos][cypos] != -1) return dist[cxpos][cypos]; 

	dist[cxpos][cypos] = 0;
	for (int dir = 0; dir < 4; dir++)
	{
		int nxpos = cxpos + dx[dir];
		int nypos = cypos + dy[dir];
		if (nxpos < 1 || nxpos > M || nypos < 1 || nypos > N) continue;
		if (board[cxpos][cypos] <= board[nxpos][nypos]) continue;
		dist[cxpos][cypos] = dist[cxpos][cypos] + dfs(nxpos, nypos);
	}
	return dist[cxpos][cypos];
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);

	cin >> M >> N;
	for (int r = 1; r <= M; r++)
	{
		for (int c = 1; c <= N; c++)
		{
			int height;
			cin >> height;
			board[r][c] = height;
		}
	}
	memset(dist, - 1, sizeof(dist));
	int ans = dfs(1, 1);
	cout << ans << endl;
}

Leave a comment