문제 링크입니다: https://school.programmers.co.kr/learn/courses/30/lessons/86054
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
a의 길이가 최대 20만이기 때문에 DP로 접근해야 하는 문제였습니다.
늦잠님 블로그 글을 참고하여 풀었습니다.
[프로그래머스/Lv.4][Java][C++] 안티세포
출처 : https://school.programmers.co.kr/learn/courses/30/lessons/86054주어진 수열의 왼쪽에서 오른쪽으로 하나 씩 보면서 숫자가 다르면 그냥 넘어가고, 같으면 넘어가거나 숫자를 합칠 수 있을 때, 경우의 수
velog.io
알고리즘은 다음과 같습니다.
1. 각 b 배열 (세그먼트)의 각 원소는 초기에는 개별 안티 세포로 존재하며, 아무 합성도 진행되지 않은 상태이므로 경우의 수는 1입니다.
2. 합성 선택 과정은 다음과 같습니다. (connect 함수)
- 현재 셀과 그 바로 왼쪽 셀의 값이 같은지 확인하여, 합성할 수 있는지 여부를 판단
- 합성이 가능할 경우 두 셀을 합쳐 값이 2배가 된 새로운 셀을 만들고, 재귀적으로 연쇄 합성 가능성을 고려하여 경우의 수 누적
- 합성하지 않았다면 이전 상태의 경우의 수를 그대로 이어받음
3. dp[i]에 각 단계까지의 누적 경우의 수를 저장하고 마지막에는 해당 세그먼트에서 가능한 모든 합성 결정의 경우의 수가 저장됩니다.
4. 파라미터로 전달되는 a는 여러 세그먼트로 나뉘어 있으므로, 각 세그먼트마다 위 과정을 독립적으로 수행한 뒤 최종 결과 dp[segmentEnd]를 반환합니다.
#include <iostream> | |
#include <vector> | |
#include <map> | |
using namespace std; | |
const int MOD = 1e9 + 7; | |
// “레벨 i”에서 각 셀(cell)의 값(merge 후 합)과 | |
// 그 값이 처음 등장한 이전 인덱스를 기록하는 map | |
vector<map<long long, int>> levelMaps; | |
// dp[i]는 “레벨 i”까지 진행했을 때 해당 상태에 도달할 수 있는 경우의 수 | |
vector<long long> dp; | |
long long connect(long long cellValue, int currentIndex, int prevIndex) | |
{ | |
// 현재 레벨에 cellValue가 기록되어 있지 않다면, (cellValue, prevIndex) 쌍을 등록 | |
if (levelMaps[currentIndex].find(cellValue) == levelMaps[currentIndex].end()) | |
{ | |
levelMaps[currentIndex][cellValue] = prevIndex; | |
} | |
// 우선 부모 셀(prevIndex)까지의 경우의 수로 초기화 | |
long long ways = dp[prevIndex]; | |
// 만약 바로 이전 레벨(prevIndex)에서 동일한 cellValue가 있었다면, | |
// merge가 가능하므로, 해당 셀과 merge하여 cellValue가 2배가 된 경우의 수를 추가 | |
if (levelMaps[prevIndex].find(cellValue) != levelMaps[prevIndex].end()) | |
{ | |
int mergeOrigin = levelMaps[prevIndex][cellValue]; | |
ways = (ways + connect(cellValue * 2, currentIndex, mergeOrigin)) % MOD; | |
} | |
return ways; | |
} | |
vector<int> solution(vector<int> a, vector<int> s) | |
{ | |
vector<int> answer; | |
int totalSize = a.size() + 1; | |
levelMaps.assign(totalSize, map<long long, int>()); | |
dp.assign(totalSize, 0); | |
int segmentStart = 0; | |
int segmentEnd = 0; | |
for (int seg = 0; seg < s.size(); seg++) | |
{ | |
int segmentLength = s[seg]; | |
segmentStart = segmentEnd; | |
segmentEnd = segmentStart + segmentLength; | |
// 세그먼트 시작 레벨 초기화 | |
// 레벨(인덱스) segmentStart는 초기 상태로, base 역할을 하며 | |
// dummy 값 (-1)을 기록해 이후 재귀의 기준 | |
levelMaps[segmentStart].clear(); | |
levelMaps[segmentStart][-1] = -1; | |
dp[segmentStart] = 1; | |
for (int i = segmentStart + 1; i <= segmentEnd; i++) | |
{ | |
dp[i] = connect(a[i - 1], i, i - 1); | |
} | |
answer.push_back((int)(dp[segmentEnd] % MOD)); | |
} | |
return answer; | |
} |

개발환경: Programmers IDE
지적, 조언, 질문 환영합니다! 질문 남겨주세요~
'알고리즘 > programmers' 카테고리의 다른 글
[Programmers] 지게차와 크레인 (0) | 2025.02.13 |
---|---|
[Programmers] 비밀 코드 해독 (0) | 2025.02.11 |
[Programmers] 미로 탈출 (0) | 2025.02.08 |
[Programmers] 매출 하락 최소화 (0) | 2025.02.05 |
[Programmers] 동굴 탐험 (0) | 2025.02.04 |