카테고리 없음
[프로그래머스 고득점 kit] 도둑질 c++ (dp)
코앤미
2023. 8. 19. 21:20
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/42897#
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 설명
우선 해당 문제는 레벨4를 책정받았는데, 이것에 너무 홀려서 어렵게만 생각하지말자.
우선 '원형' 이라는 것을 배제하고 일열로 늘어 놓는다고 가정했을 때, x번째 값을 선택한다면 x-1번째 값은 선택할 수 없다.
따라서, 'x-1번째 값을 선택하는 경우의 수'를 따지거나. 'x-2번째와 x번째를 선택하는 경우의 수' 이 두가지를 고려해서 dp를 설계하면 된다.
따라서, 아래와 같이 점화식을 만들 수 있다.
dp[i]=max(dp[i-1],dp[i-2]+money[i]);
이제 해당 문제가 '원형' 이라는 것을 고려해보자. 복잡하게 생각할 필요 없이, 크게 2가지 경우의 수로 나눌 수 있다.
1) 첫번째 값을 포함하고, 마지막 값은 포함 x -> 첫번째 값을 포함하지 않고, dp를 n번째 까지 고려하기
2) 마지막 값을 포함하고, 첫번째 값은 포함 x -> 첫번째 값을 포함하고, dp를 n-1번째까지 고려하기
위의 두가지 케이스로 나누어준다면, 원형이라는 특성을 무시할 수 있게된다.
따라서, 2개의 dp 배열을 구성하여, 각각의 dp를 구하고, 둘 중 더 큰 값을 리턴하면 된다.
정답 코드
#include <string>
#include <vector>
#include<math.h>
#include<iostream>
using namespace std;
int with_first[1000001];
int with_last[1000001];
int solution(vector<int> money) {
int siz=money.size();
with_first[0]=money[0];
with_first[1]=max(money[0],money[1]);
with_last[0]=0; //처음꺼 포함 x 가정
with_last[1]=money[1];
for(int i=2;i<siz;i++){
//처음 값 선택, 마지막값 선택 x
with_first[i]=max(with_first[i-1],with_first[i-2]+money[i]);
//마지막 값 선택, 처음값 선택 x
with_last[i]=max(with_last[i-1],with_last[i-2]+money[i]);
}
// 첫번째 값을 포함했기 때문에, 마지막 값은 무조건 포함 x 따라서 마지막 직전의 DP 사용
//(마지막-2번째 값+ 마지막 값의 경우의 수 고려 x)
int case1=with_first[siz-2];
//마지막값을 포함했기에, 마지막 값의 dp 구한다.
int case2=with_last[siz-1];
return max(case1,case2);
}