Algorithm/Algorithm 문제 풀이
[BAE/<JOON> 문제풀이] 1937. 욕심쟁이 판다 (DP.036)
폭풍저그머성찡
2020. 5. 11. 15:24
https://www.acmicpc.net/problem/1937
1937번: 욕심쟁이 판다
n*n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에서 대나무를 먹는다. 그런데 단 조건이 있다. 이 판다는 매우 욕심이 많아서 대나무를 먹고 자리를 옮기면 그 옮긴 지역에 그 전 지역보다 대나무가 많이 있어야 한다. 만약에 그런 지점이 없으면 이 판다는 불만을 가지고 단식 투쟁을 하다가 죽게 된다(-_-) 이
www.acmicpc.net
내리막길과 거의 같은 문제라서 수월하게 풀 수 있었던 것 같다.
문제의 요점은 깊이우선 탐색으로 발생하는 중복 탐색을 어떻게 효율적으로 줄이느냐 이다.
dp[x][y]를 x, y지점에서 판다가 살아 남을 수 있는 최대 일수로 지정하면
탐색의 최저점을 찍고 다시 올라 올 때 현재 지점에서 살아남을 수 있는 최대 일 수는
최저점에서의 일 수 - 현재 지점까지 살아남은 일 수 이다.
더보기
#include <iostream>
#include <vector>
using namespace std;
int mvx[5] = { 0, -1, 0, 1, 0 };
int mvy[5] = { 0, 0, -1, 0, 1 };
vector<vector<int>> arr, dp;
int n;
int maxx = -1;
int r(int x, int y, int c) {
dp[x][y] = c;
int ret = c;
for (int i = 1; i <= 4; i++) {
int mx = x + mvx[i];
int my = y + mvy[i];
if (mx > n || mx < 1 || my > n || my < 1 || arr[mx][my] <= arr[x][y]) continue;
if (dp[mx][my] != -1) {
ret = ret > dp[mx][my] + c + 1 ? ret : dp[mx][my] + c + 1;
continue;
}
int res = r(mx, my, c + 1);
ret = ret > res ? ret : res;
}
if (maxx < ret) maxx = ret;
dp[x][y] = ret - c;
return ret;
}
int main()
{
cin >> n;
arr.resize(n + 1);
dp.resize(n + 1);
for (int i = 1; i <= n; i++) {
dp[i].resize(n + 1);
arr[i].resize(n + 1);
for (int j = 1; j <= n; j++) {
cin >> arr[i][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = -1;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
r(i, j, 1);
}
}
/*for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << dp[i][j] << " ";
}
cout << endl;
}*/
cout << maxx << endl;
return 0;
}