안녕하세요.
여행벌입니다.
오늘은 BOJ 1937번 욕심쟁이 판다 문제를 다뤄보겠습니다.
Dp 와 DFS 를 조합해야 해결할 수 있는 문제로 까다로운 문제입니다.
https://www.acmicpc.net/problem/1937
1937번: 욕심쟁이 판다
n*n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에서 대나무를 먹는다. 그런데 단 조건이 있다. 이 판다는 매우 욕심이 많아서 대나무를 먹고 자리를 옮기면 그 옮긴 지역에 그 전 지역보다 대나무가 많이 있어야 한다. 만약에 그런 지점이 없으면 이 판다는 불만을 가지고 단식 투쟁을 하다가 죽게 된다(-_-) 이
www.acmicpc.net
[알고리즘풀이]
가장 먼저 생각나는 방법은 모든 곳에서 DFS 탐색을 진행하며, 가장 오래 살아남는 값을 구하는 방법입니다.
단순하고 정확하지만 시간초과에 걸립니다.
따라서 DFS 탐색을 진행하며, 더 이상 탐색을 진행하지 않아도 되는 경우에 한해서는 가지치기를 해줘야 합니다.
이를 위해 메모이제이션을 이용합니다.
똑같이 모든 곳에서 DFS 탐색을 진행해나가는데, DFS 탐색을 하며 그 지점에서 가장 오래 살아남는 값을 저장해나갑니다.
그러다 이미 탐색이 완료된 지점(값을 저장한 곳)에 방문하게 되면 더 이상 탐색을 진행하지 않고도
가장 오래 살아남는 값을 도출해낼 수 있으므로 탐색을 종료하면 됩니다.
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int map[500][500];
int dp[500][500];
int d_x[4] = { -1,0,1,0 };
int d_y[4] = { 0,-1,0,1 };
int DFS(int, int);
int main(void) {
cin >> n;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> map[i][j];
int ans = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
ans = max(ans, DFS(i, j)); // 지금까지 나온 값 중 가장 큰 값을 저장.
cout << ans;
}
int DFS(int x, int y) {
if (dp[x][y]) // 이미 탐색이 완료된 지점이라면 종료
return dp[x][y];
dp[x][y] = 1; // 아니라면 1부터 탐색 진행.
for (int i = 0; i < 4; i++) {
int n_x = x + d_x[i], n_y = y + d_y[i];
if (0 <= n_x && n_x < n && 0 <= n_y && n_y < n)
if (map[x][y] < map[n_x][n_y])
dp[x][y] = max(dp[x][y], DFS(n_x, n_y) + 1);
}
return dp[x][y];
}
'Problem Solving > BOJ' 카테고리의 다른 글
[BOJ] 15469 - N 과 M (1) (0) | 2019.09.08 |
---|---|
[BOJ] 2240 - 자두나무 (0) | 2019.09.04 |
[BOJ] 2156 - 포도주 시식 (0) | 2019.09.03 |
[BOJ] 10844 - 쉬운 계단 수 (0) | 2019.09.03 |
[BOJ] 4949 - The Balance of the World (0) | 2019.09.02 |