본문 바로가기
PS

[BAEKJOON] 1937 욕심쟁이 판다 (C++)

by bin1225 2023. 7. 17.

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

 

1937번: 욕심쟁이 판다

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

www.acmicpc.net

문제

얼필 보면 dfs 같지만 역시 시간초과가 발생한다.

n*n = 25000, 특정 점을 시작점으로 해서 dfs를 진행하면 25000 * 4 = 100000번의 연산이 필요하고, 모든 점을 시작점으로 dfs를 진행해보려면 25000 * 100000 번의 연산이 필요하므로 시간초과가 날 수 밖에 없다.

따라서 다이나믹 프로그래밍 알고리즘을 이용한다.

풀이

문제를 통해 대나무 양이 적은 곳에서 많은 곳으로만 이동한다는 점을 알 수 있다.

DP[a][b]를 (a,b)지점에 도착할 때까지 거쳐온 지점의 최대개수라고 가정한다.

DP[a][b]의 값은 (a,b)기준 상하좌우 칸의 값 중 최대값 +1 이 된다.

여기서 대나무 양이 가장 적은 칸부터 확인하면서 값을 업데이트 해둔다면, (a,b)주변 값 중 (a,b)로 이동할 수 있는 칸(대나무 양이 더 적은 칸)의 DP값은 이미 최대값으로 업데이트 되어있음을 보장할 수 있다.

따라서 우선순위 큐를 이용해서 대나무 양이 가장 적은 칸부터 좌표값을 추출하여 주변값을 확인하고 DP배열을 업데이트 한다.

업데이트 과정에서 ans값을 최대값으로 갱신한다. 

 

코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#define endl "\n"

using namespace std;

int N;
int MAP[505][505];
int DP[505][505];
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
priority_queue < pair<int, pair<int, int>>> pq;
void Input() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> MAP[i][j]; DP[i][j] = 1;
			pq.push({ -MAP[i][j],{i,j} });
		}
	}
}

void Solve() {
	
	int x, y, xx, yy, val, ans = 0;
	while (!pq.empty()) {
		auto a = pq.top(); x = a.second.second; y = a.second.first; val = -a.first;
		pq.pop();
		ans = max(ans, DP[y][x]);
		for (int i = 0; i < 4; i++) {
			xx = x + dx[i]; yy = y + dy[i];
			if (MAP[yy][xx] > MAP[y][x]) {
				DP[yy][xx] = max(DP[yy][xx], DP[y][x] + 1);
			}
		}
	}

	cout << ans;
}


int main() {
	ios::sync_with_stdio(false); cin.tie(NULL);
	freopen("input.txt", "r", stdin);
	Input();
	Solve();
	return 0;
}

 

푸바오

'PS' 카테고리의 다른 글

[BAEKJOON] 15661 링크와 스타트 (C++)  (0) 2023.07.21
[BAEKJOON] 3015 오아시스 재결합 (C++)  (0) 2023.07.19
[BAEKJOON] 5430 AC (C++)  (0) 2023.07.14
[BAEKJOON] 1987 알파벳 (C++)  (0) 2023.07.13
[BAEKJOON] 2011 암호코드 (C++)  (0) 2023.07.11