# [프로그래머스] Lv 4. 도둑질 - 동적계획법
# 문제 설명
도둑이 어느 마을을 털 계획을 하고 있습니다. 이 마을의 모든 집들은 아래 그림과 같이 동그랗게 배치되어 있습니다.
각 집들은 서로 인접한 집들과 방범장치가 연결되어 있기 때문에 인접한 두 집을 털면 경보가 울립니다.
각 집에 있는 돈이 담긴 배열 money가 주어질 때, 도둑이 훔칠 수 있는 돈의 최댓값을 return 하도록 solution 함수를 작성하세요.
# 제한사항
- 이 마을에 있는 집은 3개 이상 1,000,000개 이하입니다.
- money 배열의 각 원소는 0 이상 1,000 이하인 정수입니다.
# 입출력 예
money | return |
---|---|
[1,2,3,4] | 4 |
# 문제 풀이
- 인접한 두 집을 털지 못한다.
n
번째 집까지 계산했을 때 훔칠수 있는 돈의 최대 값은
(n-2
집까지 계산했을 때 최대값 +n
번째 집의 돈) vsn-1
집까지 계산했을 때 최대값 중에 큰 값이다.- 즉, 아래와 같이 표현할 수 있다.
dp[i] = max(dp[i-2] + money[i], dp[1])
- 첫번째 집을 털 경우에는 마지막집을 털지 못한다.
- 첫번째 집을 터는 경우와 털지 않는 경우, 2가지를 계산하여 둘 중에 큰 값을 return한다.
# 코드 구현
첫번째 집을 터는 경우에 대한 메모이제이션 배열
dp1
을 생성한다.첫번째 집을 털지 않는 경우에 대한 메모이제이션 배열
dp2
을 생성한다.dp1
의 경우, 첫번째 집을 털기 때문에 두번째 집은 털지 못한다.dp1[0] = money[0], dp1[1] = money[0]
- 마지막 집은 계산하지 말아야 하므로 moeny.length - 1 번째까지 반복하여 최대 값을 구한다.
dp2
의 경우, 첫번째 집은 털지 않으므로 첫번째 집의 값을 0으로 두고 계산한다.dp2[0] = 0, dp2[1] = money[1]
money.length 번째까지 반복하여 최대 값을 구한다.
dp1[money.length - 2]
,dp2[money.length -1]
중 더 큰 값을 return 한다.
# Java
class Solution {
public int solution(int[] money) {
int len = money.length;
int[] dp1 = new int[len-1];
int[] dp2 = new int[len];
dp1[0] = money[0];
dp1[1] = money[0];
dp2[0] = 0;
dp2[1] = money[1];
for(int i=2; i<len-1; i++) {
dp1[i] = Math.max(dp1[i-2] + money[i], dp1[i-1]);
}
for(int i=2; i<len; i++) {
dp2[i] = Math.max(dp2[i-2] + money[i], dp2[i-1]);
}
return Math.max(dp1[len-2], dp2[len-1]);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20