알고리즘

[프로그래머스] 도둑질

https://school.programmers.co.kr/learn/courses/30/lessons/42897

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

해결 아이디어를 떠올리기 어려웠던 DP 문제이다.

다른 사람의 풀이를 참고 했는데 경우의 수를 나눠서 복잡한 문제를 단순히 만드는게 풀이의 핵심이었다.

 

N개의 집이 있는 한 마을을 도둑이 털 계획을 하고 있다.

단, 각 집은 원형으로 이어져 있으며 집을 털때 서로 인접해 있는 두 개의 집을 털 수 없다. 

각 집마다 털 수 있는 돈이 배열로 주어졌을때 도둑이 이 마을에서 털 수 있는 금액의 최대값을 찾는 문제이다.

 

내가 생각한 풀이 방법

나는 DP 문제를 풀때 먼저 완전 탐색으로 문제를 해결할 수 있는지 확인하고

그 안에서 중복이 발견되면 그것을 없애는 방법으로 최적화해 나간다.

 

그래서 빈 마을에 1번 집부터 순서대로 추가하면서 도둑이 어떤 조합으로 집을 털었을때 최대인지 계산하기 위해서

마을에 집이 i 만큼 있을때 조건을 만족하면서 도둑이 털 수 있는 집들의 모든 조합을 배열의 i 번째 인덱스에 저장했다.

그래서 새로운 i+1 번째 집이 추가된 마을에서 조합을 계산할때 i 번째 인덱스에 저장된 값을 활용하려고 했다.

 

그러나 이런 방식은 중복을 제외하더라도 조합의 가짓 수를 배열에 저장해야하기 때문에

O(N^2) 만큼의 메모리와 시간을 사용해서 허용치를 초과하게 되어 다른 방법을 참고했다.

 

풀이

집이 원형이 아니라 선형으로 돼있다고 가정해보자.

도둑은 최대한으로 돈을 털기 위해 처음 집부터 마지막 집까지 순서대로 각 집을 털지 말지 고려할 것이다.

i를 0부터 N까지 반복하면서 i 번째 집까지 고려했을때 털 수 있는 돈의 최대값을 배열의 i 번째 인덱스에 저장한다.

이 상태에서 i+1번째 집을 털 경우와 아닌 경우로 나누어 생각해볼 수 있다.

(1) i+1번째 집을 털었을때 : (i-1 번째 집까지 고려한 최댓값) + (i+1 번째 집에서 털 수 있는 돈)

(2) i+1번째 집을 털지 않았을때 : i 번째 집까지 고려한 최댓값

두 경우 중 최댓값이 i+1번째 집까지 고려한 최댓값이 된다.

 

마을이 원형일때는 처음 집과 마지막 집을 동시에 털 수 없으므로

(1) 첫 번째 집을 털지 않고 마지막 집까지 고려한 경우

(2) 첫 번째 집부터 고려하되 마지막 집을 털지 않는 경우

두 경우 중 돈을 최대로 털 수 있는 경우가 정답이 된다.

 

def solution(money):
    answer = 0
    n = len(money)
    d1 = [money[0], max(money[0], money[1])] + [0]*(n-2)
    d2 = [0, money[1]] + [0]*(n-2)
    for i in range(2, n):
        if i < n-1:
            d1[i] = max(d1[i-2] + money[i], d1[i-1])
        d2[i] = max(d2[i-2] + money[i], d2[i-1])
    return max(max(d1), max(d2))

'알고리즘' 카테고리의 다른 글

[프로그래머스] 징검다리  (0) 2022.07.22
[프로그래머스] 단속카메라  (0) 2022.04.05
[프로그래머스] 큰 수 만들기  (0) 2022.03.29
백준 22942번 : 데이터 체커  (0) 2022.02.27
백준 2473번 : 세 용액  (0) 2022.02.26