728x90
반응형
1. 문제
2. 입출력 및 예제
3. 문제 해설
상하좌우가모두 탐색이 가능하다. 그리고 제약조건이 존재한다. 바로 현재 위치보다 낮은 수로만 이동할 수 있다는 점이다.
기본적으로는 dfs탐색을 해야할 거 같았다. 결국 자신의 네 방향 중 자신보다 낮은 수가 존재한다면 이동 횟수는 상관없이 이동할 수 있는 것이고 결국 오른쪽 맨 아래 칸에 도달할 수 있는 지에 대한 여부가 중요했기 때문이다.
따라서 나는 상태를 3가지로 나누었다.
- -1 : 아직 방문하지 않은 곳이다.
- 0 : 방문한 경우이다.
- 0보다 큰 수 : 현재 지점에서 목적지까지 도달 할 수 있는 경우의 수가 존재하는 곳이다.
처음에는 이 문제를 백트래킹으로 접근했는데 시간초과가 났다. 물론 4가지 방향 ^ (500 * 500)이 최악의 경우라 당연히 시간초과는 날 수 있을 것이다. 따라서 dfs를 적용하며 dp를 같이 적용했는데
백트래킹은 경로를 찾을 수 없는 경우 경우의 수가 남아있는 칸까지 다시 갔던 흔적을 지우면서 돌아와 나머지 경우의 수를 탐색하는 반면 이미 방문한 노드라면 이 지점서부터 dfs를 다시 돌려 오른쪽 아래에 도달할 수 있는 경우의 수를 memoization해주면서 왔다. 따라서 한 번 방문한 노드라면 (-1이 아니라면) 다시 돌아갈 필요없이 여기서 dfs를 다시 돌려서 오른쪽 아래에 도달 할 수 있는 지를 찾아주면 되는 것이다.
4. 코드
#pragma warning (disable : 4996)
#include <cstdio>
#include <cstring>
#define MAX 502
using namespace std;
int N, M;
int maps[MAX][MAX];
int visited[MAX][MAX];
int dy[4] = { 0,1,0,-1 };
int dx[4] = { -1,0,1,0 };
int ans;
int dfs(int y, int x) {
if (y == N - 1 && x == M - 1)return 1; // 목적지에 도착하는 경우 1을 반환
if (visited[y][x] == -1) { // 방문하지 않았다면
visited[y][x] = 0; // 방문 표시
for (int i = 0; i < 4; i++) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny < 0 || nx < 0 || ny >= N || nx >= M) continue;
if (maps[ny][nx] >= maps[y][x]) continue;
visited[y][x] += dfs(ny, nx);
//visited[ny][nx] = 0; 백트래킹은 시간초과가 난다.
}
}
return visited[y][x]; // 현재의 값을 리턴한다. 현재 경로까지 올 수 있는 경로의 수
}
void input() {
memset(visited, -1, sizeof(visited)); // visited배열 초기화
scanf("%d %d", &N, &M);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
scanf("%d", &maps[i][j]);
}
}
}
int main() {
input();
ans = dfs(0, 0);
printf("%d\n", ans);
return 0;
}
728x90
반응형
'c++ > 알고리즘' 카테고리의 다른 글
[c++] 백준-10999 구간합구하기2 (세그먼트트리, lazy_loading) (0) | 2023.02.15 |
---|---|
[c++] 백준 - 11066 파일 합치기 (dp) (0) | 2023.02.14 |
[c++] 백준 - 단절점(11266) [단절점 이론] (0) | 2023.02.13 |
[c++] 백준-스도쿠 1520 - 백트래킹 (0) | 2023.02.13 |
[c++] 백준 - 공장 (인덱스드 트리) (0) | 2023.02.09 |
댓글