백준
백준 1890 : 점프
재호맴매
2023. 11. 10. 01:03
1. 문제 : https://www.acmicpc.net/problem/1890
1890번: 점프
첫째 줄에 게임 판의 크기 N (4 ≤ N ≤ 100)이 주어진다. 그 다음 N개 줄에는 각 칸에 적혀져 있는 수가 N개씩 주어진다. 칸에 적혀있는 수는 0보다 크거나 같고, 9보다 작거나 같은 정수이며, 가장
www.acmicpc.net
2. 문제 접근
- BFS : 다음 노드로 탐색할 수 있는 방법은 두 가지이므로 자식이 2개인 트리를 탐색하는 문제로 치환할 수 있다. 다만, 최악의 경우(모든 노드의 값이 1일 때), 시작점에서 사각형의 절반만 탐색하더라도 $2^N$개의 노드를 탐색해야 한다. 4 bytes * $2^N$만 해도 메모리가 터지는 것을 확인할 수 있다.
- DP : BFS에서 메모리 초과가 나는 이유는 방문했던 노드를 중복해서 계속 방문하기 때문에 중복되는 Sub-Tree가 너무 많기 때문이다. 이를 방지하기 위해 해당 노드를 방문하는 경우의 수를 저장한다면 중복 방문하는 노드를 제거하여 많은 메모리를 아낄 수 있다. (메모이제이션)
3. 문제 해결
- 모든 좌표의 경로의 수를 0으로 초기화한다.
- 모든 좌표를 순회하며 $(i, j)$ 좌표의 값이 0일 경우, 더 이상 움직일 수 없으므로 건너뛴다.
- $(i, j)$ 좌표의 값이 0이 아닐 경우, 이동한 위치가 범위를 벗어나지 않는다면, 이동한 위치까지의 경로의 수에 $(i, j)$ 좌표까지의 경로의 수를 더한다.
- 모든 좌표를 순회한 뒤 마지막 지점의 값을 반환한다.
DP[i + Dist][j] += DP[i][j];
DP[i][j + Dist] += DP[i][j];
4. 코드
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
long solution(int N, vector<vector<int>>& map)
{
vector<vector<long>> dp;
// Initialize the dp matrix
for (int i = 0; i < N; i++)
{
vector<long> temp;
for (int j = 0; j < N; j++)
{
temp.push_back(0);
}
dp.push_back(temp);
}
// Initialize the value
dp[0][0] = 1;
// Calculate the number of the path
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (dp[i][j] == 0) continue;
if (map[i][j] == 0) continue;
int dist = map[i][j];
if (i + dist < N) // if the next point is in range
{
dp[i + dist][j] += dp[i][j];
}
if (j + dist < N) // if the next point is in range
{
dp[i][j + dist] += dp[i][j];
}
}
}
return dp[N - 1][N - 1];
}
int main()
{
int N;
vector<vector<int>> map;
cin >> N;
for (int i = 0; i < N; i++)
{
vector<int> temp;
for (int j = 0; j < N; j++)
{
int value;
cin >> value;
temp.push_back(value);
}
map.push_back(temp);
}
cout << solution(N, map);
return 0;
}