출처 : programmers.co.kr/learn/courses/30/lessons/12971
코딩테스트 연습 - 스티커 모으기(2)
N개의 스티커가 원형으로 연결되어 있습니다. 다음 그림은 N = 8인 경우의 예시입니다. 원형으로 연결된 스티커에서 몇 장의 스티커를 뜯어내어 뜯어낸 스티커에 적힌 숫자의 합이 최대가 되도록
programmers.co.kr
고려사항
- 백준에서 아주 비슷한 문제를 풀었었다.
- 첫 원소를 사용한 경우와 ( memo[1][0] ~ memo[1][len-1] )
첫 원소를 사용 안 한 경우로 나눈다 ( memo[0][0] ~ memo[0][len-1] ) - 첫 원소를 사용 했다면! 최댓값은 memo[1][len-2] 에 위치한다.
첫 원소를 사용 안했다면 최댓값은 memo[0][len-1] 에 위치한다. - 점화식은 dp[isFirst][idx] = max( dp[isFirst][idx-2] + sticker[idx], dp[isFirst][idx-1] ) 이다.
문제 조건에서 서로 인접한 수는 사용할 수 없으니! - 재귀의 base를 잘 설정해준다.
isFirst == 1 이면, dp[1][0] = sticker[0], dp[1][1] = sticker[0] ( 첫 원소를 썼다! 고로 2번째 원소는 못 쓴다! )
isFirst == 0 이면, dp[0][0] = 0, dp[0][1] = sticker[1] ( 첫 원소를 안 썼다! 고로 2번째 원소를 쓴다! )
#include <iostream> #include <vector> #include <algorithm> #include <memory.h> using namespace std; int memo[2][100000]; int dp(vector<int> &sticker, int idx, int isFirst){ int &v = memo[isFirst][idx]; if(v != -1){ return v; } v = max(dp(sticker, idx-2, isFirst)+sticker[idx], dp(sticker, idx-1, isFirst)); return v; } int solution(vector<int> sticker) { int answer = 0; int len = sticker.size(); if(len == 1){ answer = sticker[0]; return answer; } memset(memo[0], -1, 4*len); memset(memo[1], -1, 4*len); memo[1][0] = sticker[0]; memo[1][1] = sticker[0]; memo[0][0] = 0; memo[0][1] = sticker[1]; answer = max(dp(sticker, len-1, 0), dp(sticker, len-2, 1)); return answer; }