[java] 프로그래머스 - 땅따먹기
업데이트:
문제
주어진 게임판에서 각 행의 4칸 중 한칸만 밟으면서 내려올 때 얻을 수 있는 최고점을 찾는 문제.
단, 한 행씩 내려올때, 같은 열을 연속해서 밟을 수 없는 규칙이 있다.
- 예시
0 : | 1 | 2 | 3 | 5 |
1 : | 5 | 6 | 7 | 8 |
2 : | 4 | 3 | 2 | 1 |
0행의 네번째 칸, 1행의 세번째 칸, 2행의 첫번째 칸을 밟을 때의 경우, 16점이 최고점이다.
(5) + (7) + (4) = 16
(5)를 밟은 경우, 규칙에 의해 (8)은 밟을 수 없음
풀이
각 칸에서 얻을 수 있는 최고점을 저장하는 정수 배열 memo를 사용했다.
memo배열의 초기값은 가장 마지막 행을 제외한 칸에Integer.MIN_VALUE
를 저장했다
행의 갯수가 n개라면 n-1행부터 0행까지 역으로 반복문을 돌았다.
해당 차례의 행에서 열을 반복하며 같은 열이 아닌 아래행 값 중 내가 가진 칸의 값을 합했을때 가장 큰 값을 저장했다.
반복 수행 후 가장 상단의 열의 값 중 큰 값을 리턴한다.
주어진 배열(land)이 다음과 같을 경우,
| 1 | 2 | 3 | 5 |
| 5 | 6 | 7 | 8 |
| 4 | 3 | 2 | 1 |
memo배열은 다음과 같은 초기값을 가진다.
0열 1열 2열 3열
0행 : | -M | -M | -M | -M |
1행 : | -M | -M | -M | -M |
2행 : | 4 | 3 | 2 | 1 |
1행의 0열부터 3열까지 반복하며 현재 칸의 land값과 2행의 4개 열 중 더했을 때 가장 큰 값을 memo자리에 저장한다.
- 1행의 0열의 경우,
land[1][0]은 5
2행의 4개 열 중 0열이 아니며 큰 값은 land[2][1]인 3
memo[1][0]은 8을 저장한다.
1행 결과
0열 1열 2열 3열
0행 : | -M | -M | -M | -M |
1행 : | 8 | 10 | 11 | 12 |
2행 : | 4 | 3 | 2 | 1 |
2행 결과
0열 1열 2열 3열
0행 : | 13 | 14 | 15 | 16 |
1행 : | 8 | 10 | 11 | 12 |
2행 : | 4 | 3 | 2 | 1 |
memo배열의 0행 중 가장 큰 값이 정답
소스코드
import java.util.Arrays;
class Solution {
static int solution(int[][] land) {
int memo[][];
int answer = 0;
memo = new int[land.length][4];
for (int i = 0; i < memo.length - 1; i++) {
Arrays.fill(memo[i], Integer.MIN_VALUE);
}
memo[memo.length - 1] = land[land.length - 1];
for (int i = memo.length - 2; i > -1; i--) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
if (k == j)
continue;
if (memo[i][j] < land[i][j] + memo[i + 1][k]) {
memo[i][j] = land[i][j] + memo[i + 1][k];
}
}
}
}
for (int i = 0; i < 4; i++) {
answer = Math.max(answer, memo[0][i]);
}
return answer;
}
}
댓글남기기