무기 강화 주문서를 사용하여 집행검을 강화하는 시스템이 있다.
🎯 예시:
N = 4일 때
가능한 경로:
+1 +1 +1 +1
+1 +3
+2 +2
등등...
이 문제는 동적 계획법(Dynamic Programming, DP)을 통해 해결할 수 있다.
num이라 할 때,num + 1, num + 2, num + 3 중 하나로 진행 가능.Enchant(num) = Enchant(num + 1) + Enchant(num + 2) + Enchant(num + 3)int N; // 목표 강화 레벨
int cache[100]; // 메모이제이션 캐시 (최대 N은 100 미만)
N은 목표 강화 레벨cache[i]: i 레벨에서 시작해 N에 도달하는 경우의 수를 저장int Enchant(int num)
{
// 🎯 기저 사례
if (num > N) return 0; // 목표 초과: 실패
if (num == N) return 1; // 정확히 도달: 성공
// 💾 캐시 확인
int& ret = cache[num];
if (ret != -1) return ret; // 이미 계산된 값 반환
// ✅ 점화식 적용
return ret = Enchant(num + 1) + Enchant(num + 2) + Enchant(num + 3);
}
💬
num이 현재 강화 레벨일 때, 다음 레벨로 갈 수 있는 모든 경로를 탐색해 그 합을 반환한다.
int main()
{
N = 9; // 예시: +9 집행검이 뜨는 경우의 수를 구하라
memset(cache, -1, sizeof(cache)); // 캐시를 -1로 초기화
int ret = Enchant(0); // +0에서 시작
cout << ret << endl; // 결과 출력
}
Enchant(0)부터 시작해서 +N까지 가는 경우의 수 계산memset으로 캐시 초기화 안 하면 쓰레기값이 남아 오류 발생 가능!Enchant(0) = Enchant(1) + Enchant(2) + Enchant(3)
Enchant(1) = Enchant(2) + Enchant(3) + Enchant(4)
Enchant(2) = Enchant(3) + Enchant(4) + Enchant(5)
...
✅ Enchant(4) = 1 (정확히 도달)
⛔ Enchant(5) > N → 0 반환
가능한 경로:
출력: 7 (총 7가지 경로)
🎲 모든 경로의 경우의 수를 효율적으로 계산 → 출력:
149