관리 메뉴

공부 기록

백준 1937 욕심쟁이 판다 본문

코딩테스트/[BOJ] 문제 풀이

백준 1937 욕심쟁이 판다

_JAEJAE_ 2021. 8. 16. 23:32

https://www.acmicpc.net/problem/1937

 

1937번: 욕심쟁이 판다

n × n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에

www.acmicpc.net

문제

n × n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에서 대나무를 먹는다. 그런데 단 조건이 있다. 이 판다는 매우 욕심이 많아서 대나무를 먹고 자리를 옮기면 그 옮긴 지역에 그 전 지역보다 대나무가 많이 있어야 한다.

이 판다의 사육사는 이런 판다를 대나무 숲에 풀어 놓아야 하는데, 어떤 지점에 처음에 풀어 놓아야 하고, 어떤 곳으로 이동을 시켜야 판다가 최대한 많은 칸을 방문할 수 있는지 고민에 빠져 있다. 우리의 임무는 이 사육사를 도와주는 것이다. n × n 크기의 대나무 숲이 주어져 있을 때, 이 판다가 최대한 많은 칸을 이동하려면 어떤 경로를 통하여 움직여야 하는지 구하여라.

입력

첫째 줄에 대나무 숲의 크기 n(1 ≤ n ≤ 500)이 주어진다. 그리고 둘째 줄부터 n+1번째 줄까지 대나무 숲의 정보가 주어진다. 대나무 숲의 정보는 공백을 사이로 두고 각 지역의 대나무의 양이 정수 값으로 주어진다. 대나무의 양은 1,000,000보다 작거나 같은 자연수이다.

출력

첫째 줄에는 판다가 이동할 수 있는 칸의 수의 최댓값을 출력한다.

예제 입력 1 

4

14 9 12 10

1 11 5 4

7 15 2 13

6 3 16 8

예제 출력 1 

4


[풀이 과정]

이 문제도 지난번 내리막 길 문제처럼 dfs와 dp를 합쳐서 풀어야하는 문제였다.

dp[x][y]에는 판다의 처음 위치기 (x, y)일 때 이동할 수 있는 칸수이다.

 

1. (0,0)부터 (n-1, n-1)까지 모든 위치에서 eat함수를 실행한다.

 

2. eat(int x, int y)

- dp[x][y]에 값이 있다면 그 값을 리턴한다.

- 값이 없으면 1로 초기화한다. (이동을 한 번도 못하더라도 처음 위치인 (x, y)도 1번으로 치기때문)

- 상하좌우로 이동하면서 그 값이 범위를 넘지 않고 현재 값보다 큰 값인지 확인한다. (조건 : 옮긴 지역에 그 전 지역보다 대나무가 많이 있어야 한다)

- 한 번 이동할 때마다 +1씩이므로 eat(nx, ny) + 1과 현재까지 저장된 dp[x][y] 중 더 큰 값으로 업데이트한다.

 

3. 각 위치에서 칸 수 계산이 끝나면 result와 비교 후 더 큰 값으로 update한다.

4. result를 반환한다.


[소스 코드]

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 505;

int n, val, result, arr[MAX][MAX], dp[MAX][MAX];
bool visited[MAX][MAX];
int dx[] = { 0, 1, 0, -1 };
int dy[] = { -1, 0, 1, 0 };

int eat(int x, int y) {
	if (dp[x][y] != 0) return dp[x][y];

	dp[x][y] = 1;
	for (int i = 0; i < 4; i++) {
		int nx = x + dx[i];
		int ny = y + dy[i];

		if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
		
		if (arr[x][y] < arr[nx][ny]) {
			dp[x][y] = max(dp[x][y], eat(nx, ny)+1);
		}
	}
	return dp[x][y];
}

int main() {
	scanf("%d", &n);

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) scanf("%d", &arr[i][j]);
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			int val = eat(i, j);
			if (val > result) result = val;
		}
	}

	printf("%d\n", result);
	return 0;
}

https://github.com/chojaehyo/CodingTest/blob/main/%5BBOJ%5D%EC%9A%95%EC%8B%AC%EC%9F%81%EC%9D%B4%20%ED%8C%90%EB%8B%A4

 

GitHub - chojaehyo/CodingTest

Contribute to chojaehyo/CodingTest development by creating an account on GitHub.

github.com

 

'코딩테스트 > [BOJ] 문제 풀이' 카테고리의 다른 글

백준 1967 트리의 지름  (0) 2021.08.17
백준 2638 치즈  (1) 2021.08.17
백준 2573 빙산  (0) 2021.08.16
백준 1707 이분 그래프  (0) 2021.08.15
백준 1520 내리막 길  (0) 2021.08.15
Comments