안녕하세요.
여행벌입니다.

오늘은 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

+ Recent posts