https://programmers.co.kr/learn/courses/30/lessons/12913
[문제]
땅따먹기 게임을 하려고 합니다. 땅따먹기 게임의 땅(land)은 총 N행 4열로 이루어져 있고, 모든 칸에는 점수가 쓰여 있습니다. 1행부터 땅을 밟으며 한 행씩 내려올 때, 각 행의 4칸 중 한 칸만 밟으면서 내려와야 합니다. 단, 땅따먹기 게임에는 한 행씩 내려올 때, 같은 열을 연속해서 밟을 수 없는 특수 규칙이 있습니다.
예를 들면,
| 1 | 2 | 3 | 5 |
| 5 | 6 | 7 | 8 |
| 4 | 3 | 2 | 1 |
로 땅이 주어졌다면, 1행에서 네번째 칸 (5)를 밟았으면, 2행의 네번째 칸 (8)은 밟을 수 없습니다.
마지막 행까지 모두 내려왔을 때, 얻을 수 있는 점수의 최대값을 return하는 solution 함수를 완성해 주세요. 위 예의 경우, 1행의 네번째 칸 (5), 2행의 세번째 칸 (7), 3행의 첫번째 칸 (4) 땅을 밟아 16점이 최고점이 되므로 16을 return 하면 됩니다.
[제한 조건]
- 행의 개수 N : 100,000 이하의 자연수
- 열의 개수는 4개이고, 땅(land)은 2차원 배열로 주어집니다.
- 점수 : 100 이하의 자연수
[코드]
class Solution {
int solution(int[][] land) {
int answer=Integer.MIN_VALUE;
int[][] dp=new int[land.length][land[0].length];
// dp에 land의 0 번째 행에 있는 값 복사
for(int i=0;i<land[0].length;i++)
dp[0][i]=land[0][i];
// 1 번쨰 행부터 반복
for(int i=1;i<land.length;i++) {
// i번째 행의 j열 탐색
for(int j=0;j<land[i].length;j++) {
int max=Integer.MIN_VALUE;
// 4개의 행 탐색
for(int k=0;k<4;k++) {
// 현재 열 j와 이전의 열 k가 같다면 해당 땅은 밟을 수 없다.
if(j==k)
continue;
// 나머지 3개의 열에서 최댓값을 찾는다.
max=Math.max(max, dp[i-1][k]);
}
// 위에서 찾은 최댓값과 현재 땅 값을 더해 dp에 저장
dp[i][j]=land[i][j]+max;
}
}
// n-1번쨰 행에 저장된 각각의 최댓값들 중 가장 큰 값을 answer에 저장
for(int i=0;i<4;i++)
answer=Math.max(answer, dp[land.length-1][i]);
return answer;
}
}
[고찰]
이번 문제는 동적 계획법을 사용하여 해결해야 하는 문제였다. 평소 백준 단계별 풀이에서 여러 동적 계획법 문제를 풀어봤지만 여전히 어려운 파트인것 같다.
위의 문제는 0행은 dp에 미리 복사해 둔 후 1행부터 for문을 시작하면 된다. 각 열에서 0~3까지의 for문을 돌려 해당 열과 같은 값일때는 넘어가고, 나머지 3개의 열에서 최댓값을 찾아 현재 땅 값과 더한 값을 dp에 저장한다. 이 과정을 마지막 행 까지 진행하면 dp의 n-1행에는 마지막 행의 각 땅을 밟았을 때 누적되는 최댓값이 저장되어 있는데 이중 가장 큰 값을 찾아 return 하면 된다.
'프로그래머스' 카테고리의 다른 글
[프로그래머스_Level2] [3차] n진수 게임_2018 카카오 신입 공채 (0) | 2021.07.23 |
---|---|
[프로그래머스_Level2] 다음 큰 숫자 (0) | 2021.07.23 |
[프로그래머스_Level2] 숫자의 표현 (0) | 2021.07.21 |
[프로그래머스_Level2] 최댓값과 최솟값 (0) | 2021.07.21 |
[프로그래머스_Level2] 최솟값 만들기 (0) | 2021.07.21 |