반응형
격자로 나누어진 공간에서 판다가 대나무를 먹는데, 옮긴곳이 이전보다 대나무가 더 많은 곳이어야 옮겨갈 수 있습니다.
판다는 이동을 할 때, 상하좌우중 하나를 선택해서 한칸만 옮겨갈 수 있습니다.
이 판다가 최대한 많은 대나무숲에서 식사를 할 수 있도록 하고자 할 때, 최대 이동횟수를 구하는 문제입니다.
조금 어려워보이지만,
전 일단 탐욕 방법을 사용했습니다. 판다가 처음 위치한 곳의 대나무숲이 적은 곳이어야 한다는 것이죠. 그래서 최대로 많은 곳까지 가는 대나무숲을 고르는 것이죠.
\(V(s)\)의 값이 현재까지 이동한 횟수를 저장한다고 한다면,
\[ V(s) = max_{s \rightarrow s'}(V(s'))+1
형태로 작성할 수 있습니다.
이것을 동적 계획법으로 풀기 위해서는 가장 적은 값부터 출발을 해주어야 합니다. 안 그러면, 중간이 출발점이 될 수 있기 때문이죠.
최소 지점부터 시작한다면, 다음에는 다익스트라 알고리즘을 쓰든 DFS 알고리즘을 쓰든 크게 상관은 없겠죠. 제 경우에는 효율을 위해서 동적 계획법을 썼습니다. 알고리즘 효율은 \(O(n^2 \log n)\) 으로 정렬 비용입니다.
//-----------------------------------------------------
// baekjoon #1937
// - by Aubrey Choi
// - created at 2019-10-16
//-----------------------------------------------------
#include <stdio.h>
#include <algorithm>
static int dp[502*502], m[502*502];
bool cmp(int a, int b) { return m[a]<m[b]; }
int main()
{
int n, v[500*500], ans=1;
scanf("%d", &n);
for(int i=0;i<n*n;i++) v[i]=(i/n+1)*(n+2)+(i%n+1), scanf("%d",&m[v[i]]);
std::sort(v,v+n*n,cmp);
int d[4]={n+2,1,-1,-n-2};
for(int i=0;i<n*n;i++)
{
int s = v[i], max = 0;
for(int j=0;j<4;j++) if(max<dp[s+d[j]]&&m[s+d[j]]!=m[s]) max=dp[s+d[j]];
dp[s]=max+1; if(ans<max+1) ans=max+1;
}
printf("%d\n", ans);
}
728x90
'Programming > BOJ' 카테고리의 다른 글
[C/C++] 백준 #1940 주몽(두개의 포인터) (0) | 2022.11.29 |
---|---|
[C/C++] 백준 #1939 중량제한(그래프) (0) | 2022.11.19 |
[C/C++] 백준 #1935 후위 표기식2(스택) (0) | 2022.11.16 |
[C/C++] 백준 #1932 정수 삼각형(동적 계획법) (0) | 2022.11.14 |
[C/C++] #1931 회의실 배정(탐욕) (0) | 2022.11.13 |
댓글