공부 기록
백준 1937 욕심쟁이 판다 본문
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;
}
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 |